From 3f8c47367830f9686b91c2c32158940de4c65466 Mon Sep 17 00:00:00 2001 From: Ella Date: Sun, 17 Apr 2022 01:33:16 -0700 Subject: [PATCH 001/122] Fix typo: recomment -> recommend --- content/notes/obsidian.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/notes/obsidian.md b/content/notes/obsidian.md index a10379e09..ac2e3e965 100644 --- a/content/notes/obsidian.md +++ b/content/notes/obsidian.md @@ -26,4 +26,4 @@ Inserting front matter everytime you want to create a new Note gets annoying rea **If you decide to overwrite the `/content` folder completely, don't remove the `/content/templates` folder!** -Head over to Options > Core Plugins and enable the Templates plugin. Then go to Options > Hotkeys and set a hotkey for 'Insert Template' (I recomment `[cmd]+T`). That way, when you create a new note, you can just press the hotkey for a new template and be ready to go! +Head over to Options > Core Plugins and enable the Templates plugin. Then go to Options > Hotkeys and set a hotkey for 'Insert Template' (I recommend `[cmd]+T`). That way, when you create a new note, you can just press the hotkey for a new template and be ready to go! From 0cfd93c57cdb31c0f0c48bddb407158ea2e0d7db Mon Sep 17 00:00:00 2001 From: Ella Date: Sun, 17 Apr 2022 02:11:17 -0700 Subject: [PATCH 002/122] Fix another typo --- content/notes/obsidian.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/notes/obsidian.md b/content/notes/obsidian.md index ac2e3e965..8e5fedd82 100644 --- a/content/notes/obsidian.md +++ b/content/notes/obsidian.md @@ -16,7 +16,7 @@ The easiest way to use an existing Vault is to copy all of your files (directory ## Settings Great, now that you have your Obsidian linked to your Quartz, let's fix some settings so that they play well. -1. Under Options > Files and Links, set the New link format to always e Absolute Path in Vault. +1. Under Options > Files and Links, set the New link format to always use Absolute Path in Vault. 2. Go to Settings > Files & Links > Turn "on" automatically update internal links. ![Obsidian Settings](/notes/images/obsidian-settings.png)*Obsidian Settings* From 3c7ece5405436c85282f156cf387b11d08cc2d87 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 28 Apr 2022 10:48:31 -0700 Subject: [PATCH 003/122] fix: append trailing slash, fixes #111 --- assets/js/graph.js | 2 +- assets/js/search.js | 2 +- layouts/partials/backlinks.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index f0b1f7f6f..08c97e996 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -127,7 +127,7 @@ async function drawGraph(url, baseUrl, pathColors, depth, enableDrag, enableLege .attr("fill", color) .style("cursor", "pointer") .on("click", (_, d) => { - window.location.href = baseUrl + '/' + decodeURI(d.id).replace(/\s+/g, '-') + window.location.href = `${baseUrl}/${decodeURI(d.id).replace(/\s+/g, '-')}/` }) .on("mouseover", function(_, d) { d3.selectAll(".node") diff --git a/assets/js/search.js b/assets/js/search.js index facebe56d..0aacb5f44 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -131,7 +131,7 @@ const removeMarkdown = ( } const redir = (id, term) => { - window.location.href = BASE_URL + `${id}#:~:text=${encodeURIComponent(term)}` + window.location.href = `${BASE_URL}${id}#:~:text=${encodeURIComponent(term)}/` } const formatForDisplay = id => ({ diff --git a/layouts/partials/backlinks.html b/layouts/partials/backlinks.html index 425ec67cf..deb82e82e 100644 --- a/layouts/partials/backlinks.html +++ b/layouts/partials/backlinks.html @@ -9,7 +9,7 @@ {{if $inbound}} {{$cleanedInbound := apply (apply $inbound "index" "." "source") "replace" "." " " "-"}} {{- range $cleanedInbound | uniq -}} - {{$l := printf "%s%s" $host .}} + {{$l := printf "%s%s/" $host .}} {{with (index $contentTable .)}}
  • {{index (index . "title")}} From c8d390dbc5a749af533f1ec05de2d5b6f37fa156 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 28 Apr 2022 13:45:29 -0700 Subject: [PATCH 004/122] fix: always hide popover on mobile (fixes #104) --- assets/styles/base.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 1be022933..0c7d9576a 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -526,7 +526,7 @@ header { box-shadow: 6px 6px 36px 0px rgba(0,0,0,0.25); @media all and (max-width: 600px) { - display: none; + display: none !important; } &.visible { From 87b5a7a2519c70b6f6e678c6b86a3aefc4dd3218 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 28 Apr 2022 15:49:16 -0700 Subject: [PATCH 005/122] feat: show graph titles on zoom (fixes #92) --- assets/js/graph.js | 33 ++++++++++++++++++++++----------- assets/styles/base.scss | 6 ++++++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index 08c97e996..db2a171fd 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -70,12 +70,12 @@ async function drawGraph(url, baseUrl, pathColors, depth, enableDrag, enableLege .on("end", enableDrag ? dragended : noop); } - const height = 250 + const height = Math.max(document.getElementById("graph-container").offsetHeight, 250) const width = document.getElementById("graph-container").offsetWidth const simulation = d3.forceSimulation(data.nodes) .force("charge", d3.forceManyBody().strength(-30)) - .force("link", d3.forceLink(data.links).id(d => d.id)) + .force("link", d3.forceLink(data.links).id(d => d.id).distance(40)) .force("center", d3.forceCenter()); const svg = d3.select('#graph-container') @@ -115,15 +115,18 @@ async function drawGraph(url, baseUrl, pathColors, depth, enableDrag, enableLege .data(data.nodes) .enter().append("g") + // calculate radius + const nodeRadius = (d) => { + const numOut = index.links[d.id]?.length || 0 + const numIn = index.backlinks[d.id]?.length || 0 + return 3 + (numOut + numIn) / 4 + } + // 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("r", nodeRadius) .attr("fill", color) .style("cursor", "pointer") .on("click", (_, d) => { @@ -154,11 +157,12 @@ async function drawGraph(url, baseUrl, pathColors, depth, enableDrag, enableLege // show text for self d3.select(this.parentNode) - .select("text") .raise() + .select("text") .transition() .duration(200) .style("opacity", 1) + .raise() }).on("mouseleave", function(_, d) { d3.selectAll(".node") .transition() @@ -183,11 +187,14 @@ async function drawGraph(url, baseUrl, pathColors, depth, enableDrag, enableLege // draw labels const labels = graphNode.append("text") - .attr("dx", 12) - .attr("dy", ".35em") + .attr("dx", 0) + .attr("dy", d => nodeRadius(d) + 8 + "px") + .attr("text-anchor", "middle") .text((d) => content[d.id]?.title || d.id.replace("-", " ")) .style("opacity", 0) .style("pointer-events", "none") + .style("font-size", "0.4em") + .raise() .call(drag(simulation)); // set panning @@ -199,7 +206,11 @@ async function drawGraph(url, baseUrl, pathColors, depth, enableDrag, enableLege .on("zoom", ({ transform }) => { link.attr("transform", transform); node.attr("transform", transform); - labels.attr("transform", transform); + const scale = transform.k + const scaledOpacity = Math.max((scale - 1) / 3.75, 0) + labels + .attr("transform", transform) + .style("opacity", scaledOpacity) })); } diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 0c7d9576a..4d03a06a3 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -329,6 +329,12 @@ hr { & #graph-container { border: var(--outlinegray) 1px solid; border-radius: 5px; + box-sizing: border-box; + + & > svg { + margin-bottom: -5px; + + } } } From b8a660e208333ea8ef4998c2f815411f12ce7067 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 30 Apr 2022 13:10:12 -0700 Subject: [PATCH 006/122] feat: copyable header anchors (fixes #86) --- assets/styles/base.scss | 13 +++++++++++++ layouts/partials/textprocessing.html | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 4d03a06a3..3b2801bfc 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -12,6 +12,19 @@ h1, h2, h3, h4, h5, h6, ol, ul, thead { font-weight: revert; margin: revert; padding: revert; + + &:hover > .hanchor { + opacity: 1; + } +} + +.hanchor { + font-family: Inter; + margin-left: -1em; + opacity: 0.3; + transition: opacity 0.3s ease; + color: var(--secondary); + } p, ul, text { diff --git a/layouts/partials/textprocessing.html b/layouts/partials/textprocessing.html index 2312aa461..8e8c99917 100644 --- a/layouts/partials/textprocessing.html +++ b/layouts/partials/textprocessing.html @@ -53,4 +53,8 @@ {{end}} {{end}} {{end}} + +{{/* Add copyable anchors */}} +{{ $content = $content | replaceRE "()(.+)()" `${1}# ${3}${4}` }} + {{ $content | safeHTML }} From 416dc0b85cabfbb1dced0262b11256fa258f5ee9 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 30 Apr 2022 13:13:30 -0700 Subject: [PATCH 007/122] fix: add update for local hugo-obsidian on make update --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9beee0f84..0d29bdacf 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,14 @@ help: ## Show all Makefile targets @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' update: ## Update Quartz to the latest version on Github + go install github.com/jackyzha0/hugo-obsidian@latest @git remote show upstream || (echo "remote 'upstream' not present, setting 'upstream'" && git remote add upstream https://github.com/jackyzha0/quartz.git) git fetch upstream git log --oneline --decorate --graph ..upstream/hugo git checkout -p upstream/hugo -- layouts .github Makefile assets/js assets/styles/base.scss assets/styles/darkmode.scss config.toml data -update-force: ## Forcefully pull all changes and don't ask to patch +update-force: ## Forcefully pull all changes and don't ask to patch + go install github.com/jackyzha0/hugo-obsidian@latest @git remote show upstream || (echo "remote 'upstream' not present, setting 'upstream'" && git remote add upstream https://github.com/jackyzha0/quartz.git) git fetch upstream git checkout upstream/hugo -- layouts .github Makefile assets/js assets/styles/base.scss assets/styles/darkmode.scss config.toml data From bcb166c21cf4cf6d923608c12729373cf926eddb Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Sun, 1 May 2022 22:06:33 -0700 Subject: [PATCH 008/122] Add router --- assets/js/graph.js | 312 +++++++++++++++++++++--------------- assets/js/search.js | 283 +++++++++++++++++--------------- layouts/partials/graph.html | 31 ++-- layouts/partials/head.html | 121 +++++++++----- 4 files changed, 427 insertions(+), 320 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index db2a171fd..939fd99d8 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -1,51 +1,73 @@ -async function drawGraph(url, baseUrl, pathColors, depth, enableDrag, enableLegend, enableZoom) { - const { index, links, content } = await fetchData - const curPage = url.replace(baseUrl, "") +async function drawGraph( + url, + baseUrl, + pathColors, + depth, + enableDrag, + enableLegend, + enableZoom +) { + const container = document.getElementById('graph-container'); - const parseIdsFromLinks = (links) => [...(new Set(links.flatMap(link => ([link.source, link.target]))))] + const { index, links, content } = await fetchData; + const curPage = url.replace(baseUrl, ''); - const neighbours = new Set() - const wl = [curPage || "/", "__SENTINEL"] + const parseIdsFromLinks = (links) => [ + ...new Set(links.flatMap((link) => [link.source, link.target])), + ]; + + // links is mutated by d3 + // we want to use links later on, so we make a copy and pass + // that one to d3 + const copyLinks = JSON.parse(JSON.stringify(links)); + + const neighbours = new Set(); + const wl = [curPage || '/', '__SENTINEL']; if (depth >= 0) { while (depth >= 0 && wl.length > 0) { // compute neighbours - const cur = wl.shift() - if (cur === "__SENTINEL") { - depth-- - wl.push("__SENTINEL") + const cur = wl.shift(); + if (cur === '__SENTINEL') { + depth--; + wl.push('__SENTINEL'); } else { - neighbours.add(cur) - const outgoing = index.links[cur] || [] - const incoming = index.backlinks[cur] || [] - wl.push(...outgoing.map(l => l.target), ...incoming.map(l => l.source)) + neighbours.add(cur); + const outgoing = index.links[cur] || []; + const incoming = index.backlinks[cur] || []; + wl.push( + ...outgoing.map((l) => l.target), + ...incoming.map((l) => l.source) + ); } } } else { - parseIdsFromLinks(links).forEach(id => neighbours.add(id)) + parseIdsFromLinks(copyLinks).forEach((id) => neighbours.add(id)); } const data = { - nodes: [...neighbours].map(id => ({ id })), - links: links.filter(l => neighbours.has(l.source) && neighbours.has(l.target)), - } + nodes: [...neighbours].map((id) => ({ id })), + links: copyLinks.filter( + (l) => neighbours.has(l.source) && neighbours.has(l.target) + ), + }; const color = (d) => { - if (d.id === curPage || (d.id === "/" && curPage === "")) { - return "var(--g-node-active)" + if (d.id === curPage || (d.id === '/' && curPage === '')) { + return 'var(--g-node-active)'; } for (const pathColor of pathColors) { - const path = Object.keys(pathColor)[0] - const colour = pathColor[path] + const path = Object.keys(pathColor)[0]; + const colour = pathColor[path]; if (d.id.startsWith(path)) { - return colour + return colour; } } - return "var(--g-node)" - } + return 'var(--g-node)'; + }; - const drag = simulation => { + const drag = (simulation) => { function dragstarted(event, d) { if (!event.active) simulation.alphaTarget(1).restart(); d.fx = d.x; @@ -63,169 +85,197 @@ async function drawGraph(url, baseUrl, pathColors, depth, enableDrag, enableLege d.fy = null; } - const noop = () => { } - return d3.drag() - .on("start", enableDrag ? dragstarted : noop) - .on("drag", enableDrag ? dragged : noop) - .on("end", enableDrag ? dragended : noop); - } + const noop = () => {}; + return d3 + .drag() + .on('start', enableDrag ? dragstarted : noop) + .on('drag', enableDrag ? dragged : noop) + .on('end', enableDrag ? dragended : noop); + }; - const height = Math.max(document.getElementById("graph-container").offsetHeight, 250) - const width = document.getElementById("graph-container").offsetWidth + const height = Math.max(container.offsetHeight, 250); + const width = container.offsetWidth; - const simulation = d3.forceSimulation(data.nodes) - .force("charge", d3.forceManyBody().strength(-30)) - .force("link", d3.forceLink(data.links).id(d => d.id).distance(40)) - .force("center", d3.forceCenter()); + const simulation = d3 + .forceSimulation(data.nodes) + .force('charge', d3.forceManyBody().strength(-30)) + .force( + 'link', + d3 + .forceLink(data.links) + .id((d) => d.id) + .distance(40) + ) + .force('center', d3.forceCenter()); - const svg = d3.select('#graph-container') + const svg = d3 + .select('#graph-container') .append('svg') .attr('width', width) .attr('height', height) - .attr("viewBox", [-width / 2, -height / 2, width, height]); + .attr('viewBox', [-width / 2, -height / 2, width, height]); if (enableLegend) { const legend = [ - { "Current": "var(--g-node-active)" }, - { "Note": "var(--g-node)" }, - ...pathColors - ] + { 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") - }) + 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") + 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) + .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") + const graphNode = svg + .append('g') + .selectAll('g') .data(data.nodes) - .enter().append("g") + .enter() + .append('g'); // calculate radius const nodeRadius = (d) => { - const numOut = index.links[d.id]?.length || 0 - const numIn = index.backlinks[d.id]?.length || 0 - return 3 + (numOut + numIn) / 4 - } + const numOut = index.links[d.id]?.length || 0; + const numIn = index.backlinks[d.id]?.length || 0; + return 3 + (numOut + numIn) / 4; + }; // draw individual nodes - const node = graphNode.append("circle") - .attr("class", "node") - .attr("id", (d) => d.id) - .attr("r", nodeRadius) - .attr("fill", color) - .style("cursor", "pointer") - .on("click", (_, d) => { - window.location.href = `${baseUrl}/${decodeURI(d.id).replace(/\s+/g, '-')}/` + const node = graphNode + .append('circle') + .attr('class', 'node') + .attr('id', (d) => d.id) + .attr('r', nodeRadius) + .attr('fill', color) + .style('cursor', 'pointer') + .on('click', (_, d) => { + window.navigate( + new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, '-')}/`), + '.singlePage' + ); }) - .on("mouseover", function(_, d) { - d3.selectAll(".node") + .on('mouseover', function (_, d) { + d3.selectAll('.node') .transition() .duration(100) - .attr("fill", "var(--g-node-inactive)") + .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 linkNodes = d3.selectAll(".link").filter(d => d.source.id === currentId || d.target.id === currentId) + 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 linkNodes = d3 + .selectAll('.link') + .filter((d) => d.source.id === currentId || d.target.id === currentId); // highlight neighbour nodes - neighbourNodes - .transition() - .duration(200) - .attr("fill", color) + neighbourNodes.transition().duration(200).attr('fill', color); // highlight links linkNodes .transition() .duration(200) - .attr("stroke", "var(--g-link-active)") + .attr('stroke', 'var(--g-link-active)'); // show text for self d3.select(this.parentNode) .raise() - .select("text") + .select('text') .transition() .duration(200) - .style("opacity", 1) - .raise() - }).on("mouseleave", function(_, d) { - d3.selectAll(".node") - .transition() - .duration(200) - .attr("fill", color) + .style('opacity', 1); + }) + .on('mouseleave', function (_, d) { + d3.selectAll('.node').transition().duration(200).attr('fill', color); - const currentId = d.id - const linkNodes = d3.selectAll(".link").filter(d => d.source.id === currentId || d.target.id === currentId) + const currentId = d.id; + const linkNodes = d3 + .selectAll('.link') + .filter((d) => d.source.id === currentId || d.target.id === currentId); - linkNodes - .transition() - .duration(200) - .attr("stroke", "var(--g-link)") + linkNodes.transition().duration(200).attr('stroke', 'var(--g-link)'); d3.select(this.parentNode) - .select("text") + .select('text') .transition() .duration(200) - .style("opacity", 0) + .style('opacity', 0); }) .call(drag(simulation)); // draw labels - const labels = graphNode.append("text") - .attr("dx", 0) - .attr("dy", d => nodeRadius(d) + 8 + "px") - .attr("text-anchor", "middle") - .text((d) => content[d.id]?.title || d.id.replace("-", " ")) - .style("opacity", 0) - .style("pointer-events", "none") - .style("font-size", "0.4em") + const labels = graphNode + .append('text') + .attr('dx', 0) + .attr('dy', (d) => nodeRadius(d) + 8 + 'px') + .attr('text-anchor', 'middle') + .text((d) => content[d.id]?.title || d.id.replace('-', ' ')) + .style('opacity', 0) + .style('pointer-events', 'none') + .style('font-size', '0.4em') .raise() .call(drag(simulation)); // set panning 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); - const scale = transform.k - const scaledOpacity = Math.max((scale - 1) / 3.75, 0) - labels - .attr("transform", transform) - .style("opacity", scaledOpacity) - })); + svg.call( + d3 + .zoom() + .extent([ + [0, 0], + [width, height], + ]) + .scaleExtent([0.25, 4]) + .on('zoom', ({ transform }) => { + link.attr('transform', transform); + node.attr('transform', transform); + const scale = transform.k; + const scaledOpacity = Math.max((scale - 1) / 3.75, 0); + labels.attr('transform', transform).style('opacity', scaledOpacity); + }) + ); } // progress the simulation - simulation.on("tick", () => { + 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) + .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); }); } diff --git a/assets/js/search.js b/assets/js/search.js index 0aacb5f44..212b2c730 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -9,47 +9,47 @@ const removeMarkdown = ( preserveLinks: false, } ) => { - let output = markdown || ""; - output = output.replace(/^(-\s*?|\*\s*?|_\s*?){3,}\s*$/gm, ""); + let output = markdown || ''; + output = output.replace(/^(-\s*?|\*\s*?|_\s*?){3,}\s*$/gm, ''); try { if (options.stripListLeaders) { if (options.listUnicodeChar) output = output.replace( /^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, - options.listUnicodeChar + " $1" + options.listUnicodeChar + ' $1' ); - else output = output.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, "$1"); + else output = output.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, '$1'); } if (options.gfm) { output = output - .replace(/\n={2,}/g, "\n") - .replace(/~{3}.*\n/g, "") - .replace(/~~/g, "") - .replace(/`{3}.*\n/g, ""); + .replace(/\n={2,}/g, '\n') + .replace(/~{3}.*\n/g, '') + .replace(/~~/g, '') + .replace(/`{3}.*\n/g, ''); } if (options.preserveLinks) { - output = output.replace(/\[(.*?)\][\[\(](.*?)[\]\)]/g, "$1 ($2)") + output = output.replace(/\[(.*?)\][\[\(](.*?)[\]\)]/g, '$1 ($2)'); } output = output - .replace(/<[^>]*>/g, "") - .replace(/^[=\-]{2,}\s*$/g, "") - .replace(/\[\^.+?\](\: .*?$)?/g, "") - .replace(/\s{0,2}\[.*?\]: .*?$/g, "") - .replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, options.useImgAltText ? "$1" : "") - .replace(/\[(.*?)\][\[\(].*?[\]\)]/g, "$1") - .replace(/^\s{0,3}>\s?/g, "") - .replace(/(^|\n)\s{0,3}>\s?/g, "\n\n") - .replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, "") + .replace(/<[^>]*>/g, '') + .replace(/^[=\-]{2,}\s*$/g, '') + .replace(/\[\^.+?\](\: .*?$)?/g, '') + .replace(/\s{0,2}\[.*?\]: .*?$/g, '') + .replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, options.useImgAltText ? '$1' : '') + .replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1') + .replace(/^\s{0,3}>\s?/g, '') + .replace(/(^|\n)\s{0,3}>\s?/g, '\n\n') + .replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '') .replace( /^(\n)?\s{0,}#{1,6}\s+| {0,}(\n)?\s{0,}#{0,} {0,}(\n)?\s{0,}$/gm, - "$1$2$3" + '$1$2$3' ) - .replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, "$2") - .replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, "$2") - .replace(/(`{3,})(.*?)\1/gm, "$2") - .replace(/`(.+?)`/g, "$1") - .replace(/\n{2,}/g, "\n\n"); + .replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, '$2') + .replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, '$2') + .replace(/(`{3,})(.*?)\1/gm, '$2') + .replace(/`(.+?)`/g, '$1') + .replace(/\n{2,}/g, '\n\n'); } catch (e) { console.error(e); return markdown; @@ -58,182 +58,205 @@ const removeMarkdown = ( }; // ----- -(async function() { - const encoder = str => str.toLowerCase().split(/([^a-z]|[^\x00-\x7F])+/) +(async function () { + const encoder = (str) => str.toLowerCase().split(/([^a-z]|[^\x00-\x7F])+/); const contentIndex = new FlexSearch.Document({ cache: true, - charset: "latin:extra", + charset: 'latin:extra', optimize: true, - index: [{ - field: "content", - tokenize: "reverse", - encode: encoder, - }, { - field: "title", - tokenize: "forward", - encode: encoder, - }] - }) + index: [ + { + field: 'content', + tokenize: 'reverse', + encode: encoder, + }, + { + field: 'title', + tokenize: 'forward', + encode: encoder, + }, + ], + }); - const { content } = await fetchData + const { content } = await fetchData; for (const [key, value] of Object.entries(content)) { contentIndex.add({ id: key, title: value.title, content: removeMarkdown(value.content), - }) + }); } const highlight = (content, term) => { - const highlightWindow = 20 - const tokenizedTerm = term.split(/\s+/).filter(t => t !== "") - const splitText = content.split(/\s+/).filter(t => t !== "") - const includesCheck = (token) => tokenizedTerm.some(term => token.toLowerCase().startsWith(term.toLowerCase())) + const highlightWindow = 20; + const tokenizedTerm = term.split(/\s+/).filter((t) => t !== ''); + const splitText = content.split(/\s+/).filter((t) => t !== ''); + const includesCheck = (token) => + tokenizedTerm.some((term) => + token.toLowerCase().startsWith(term.toLowerCase()) + ); - const occurrencesIndices = splitText - .map(includesCheck) + const occurrencesIndices = splitText.map(includesCheck); // calculate best index - let bestSum = 0 - let bestIndex = 0 - for (let i = 0; i < Math.max(occurrencesIndices.length - highlightWindow, 0); i++) { - const window = occurrencesIndices.slice(i, i + highlightWindow) - const windowSum = window.reduce((total, cur) => total + cur, 0) + let bestSum = 0; + let bestIndex = 0; + for ( + let i = 0; + i < Math.max(occurrencesIndices.length - highlightWindow, 0); + i++ + ) { + const window = occurrencesIndices.slice(i, i + highlightWindow); + const windowSum = window.reduce((total, cur) => total + cur, 0); if (windowSum >= bestSum) { - bestSum = windowSum - bestIndex = i + bestSum = windowSum; + bestIndex = i; } } - const startIndex = Math.max(bestIndex - highlightWindow, 0) - const endIndex = Math.min(startIndex + 2 * highlightWindow, splitText.length) + const startIndex = Math.max(bestIndex - highlightWindow, 0); + const endIndex = Math.min( + startIndex + 2 * highlightWindow, + splitText.length + ); const mappedText = splitText .slice(startIndex, endIndex) - .map(token => { + .map((token) => { if (includesCheck(token)) { - return `${token}` + return `${token}`; } - return token + return token; }) - .join(" ") - .replaceAll(' ', " ") - return `${startIndex === 0 ? "" : "..."}${mappedText}${endIndex === splitText.length ? "" : "..."}` - } + .join(' ') + .replaceAll(' ', ' '); + return `${startIndex === 0 ? '' : '...'}${mappedText}${ + endIndex === splitText.length ? '' : '...' + }`; + }; const resultToHTML = ({ url, title, content, term }) => { - const text = removeMarkdown(content) - const resultTitle = highlight(title, term) - const resultText = highlight(text, term) + const text = removeMarkdown(content); + const resultTitle = highlight(title, term); + const resultText = highlight(text, term); return `` - } + `; + }; const redir = (id, term) => { - window.location.href = `${BASE_URL}${id}#:~:text=${encodeURIComponent(term)}/` - } + window.navigate( + new URL( + `${BASE_URL.slice(0, -1)}${id}#:~:text=${encodeURIComponent(term)}/` + ), + '.singlePage' + ); + closeSearch(); + }; - const formatForDisplay = id => ({ + const formatForDisplay = (id) => ({ id, url: id, title: content[id].title, - content: content[id].content - }) + content: content[id].content, + }); - const source = document.getElementById('search-bar') - const results = document.getElementById("results-container") - let term - source.addEventListener("keyup", (e) => { - if (e.key === "Enter") { - const anchor = document.getElementsByClassName("result-card")[0] - redir(anchor.id, term) + const source = document.getElementById('search-bar'); + const results = document.getElementById('results-container'); + let term; + source.addEventListener('keyup', (e) => { + if (e.key === 'Enter') { + const anchor = document.getElementsByClassName('result-card')[0]; + redir(anchor.id, term); } - }) + }); source.addEventListener('input', (e) => { - term = e.target.value + term = e.target.value; const searchResults = contentIndex.search(term, [ { - field: "content", + field: 'content', limit: 10, }, { - field: "title", + field: 'title', limit: 5, - } - ]) - const getByField = field => { - const results = searchResults.filter(x => x.field === field) + }, + ]); + const getByField = (field) => { + const results = searchResults.filter((x) => x.field === field); if (results.length === 0) { - return [] + return []; } else { - return [...results[0].result] + return [...results[0].result]; } - } - const allIds = new Set([...getByField('title'), ...getByField('content')]) - const finalResults = [...allIds].map(formatForDisplay) + }; + const allIds = new Set([...getByField('title'), ...getByField('content')]); + const finalResults = [...allIds].map(formatForDisplay); // display if (finalResults.length === 0) { results.innerHTML = `` + `; } else { results.innerHTML = finalResults - .map(result => resultToHTML({ - ...result, - term, - })) - .join("\n") - const anchors = document.getElementsByClassName("result-card"); - [...anchors].forEach(anchor => { - anchor.onclick = () => redir(anchor.id, term) - }) + .map((result) => + resultToHTML({ + ...result, + term, + }) + ) + .join('\n'); + const anchors = document.getElementsByClassName('result-card'); + [...anchors].forEach((anchor) => { + anchor.onclick = () => redir(anchor.id, term); + }); } - }) + }); - - const searchContainer = document.getElementById("search-container") + const searchContainer = document.getElementById('search-container'); function openSearch() { - if (searchContainer.style.display === "none" || searchContainer.style.display === "") { - source.value = "" - results.innerHTML = "" - searchContainer.style.display = "block" - source.focus() + if ( + searchContainer.style.display === 'none' || + searchContainer.style.display === '' + ) { + source.value = ''; + results.innerHTML = ''; + searchContainer.style.display = 'block'; + source.focus(); } else { - searchContainer.style.display = "none" + searchContainer.style.display = 'none'; } } function closeSearch() { - searchContainer.style.display = "none" + searchContainer.style.display = 'none'; } document.addEventListener('keydown', (event) => { - if (event.key === "k" && (event.ctrlKey || event.metaKey)) { - event.preventDefault() - openSearch() + if (event.key === 'k' && (event.ctrlKey || event.metaKey)) { + event.preventDefault(); + openSearch(); } - if (event.key === "Escape") { - event.preventDefault() - closeSearch() + if (event.key === 'Escape') { + event.preventDefault(); + closeSearch(); } - }) + }); - const searchButton = document.getElementById("search-icon") + const searchButton = document.getElementById('search-icon'); searchButton.addEventListener('click', (evt) => { - openSearch() - }) + openSearch(); + }); searchButton.addEventListener('keydown', (evt) => { - openSearch() - }) + openSearch(); + }); searchContainer.addEventListener('click', (evt) => { - closeSearch() - }) - document.getElementById("search-space").addEventListener('click', (evt) => { - evt.stopPropagation() - }) -})() - + closeSearch(); + }); + document.getElementById('search-space').addEventListener('click', (evt) => { + evt.stopPropagation(); + }); +})(); diff --git a/layouts/partials/graph.html b/layouts/partials/graph.html index ca379689b..b9f79763c 100644 --- a/layouts/partials/graph.html +++ b/layouts/partials/graph.html @@ -1,25 +1,18 @@ - +

    Interactive Graph

    {{ $js := resources.Get "js/graph.js" | resources.Fingerprint "md5" }} - diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 195cade44..772153ada 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -1,46 +1,87 @@ - - - - {{ if .Title }}{{ .Title }}{{ else }}{{ $.Site.Data.config.page_title }}{{ end }} - - + + + + + {{ if .Title }}{{ .Title }}{{ else }}{{ $.Site.Data.config.page_title }}{{ + end }} + + + - - - {{$sass := resources.Match "styles/[!_]*.scss" }} - {{$css := slice }} - {{range $sass}} - {{$scss := . | resources.ToCSS (dict "outputStyle" "compressed") }} - {{$css = $css | append $scss}} - {{end}} - {{$finalCss := $css | resources.Concat "styles.css" | resources.Fingerprint "md5" | resources.Minify }} - + + + {{$sass := resources.Match "styles/[!_]*.scss" }} {{$css := slice }} {{range + $sass}} {{$scss := . | resources.ToCSS (dict "outputStyle" "compressed") }} + {{$css = $css | append $scss}} {{end}} {{$finalCss := $css | resources.Concat + "styles.css" | resources.Fingerprint "md5" | resources.Minify }} + - {{ $darkMode := resources.Get "js/darkmode.js" | resources.Fingerprint "md5" | resources.Minify }} - - {{partial "katex.html" .}} + {{ $darkMode := resources.Get "js/darkmode.js" | resources.Fingerprint "md5" | + resources.Minify }} + + {{partial "katex.html" .}} - - {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint "md5" | resources.Minify | }} - {{$contentIndex := resources.Get "indices/contentIndex.json" | resources.Fingerprint "md5" | resources.Minify }} - + + {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint + "md5" | resources.Minify | }} {{$contentIndex := resources.Get + "indices/contentIndex.json" | resources.Fingerprint "md5" | resources.Minify + }} + + {{ template "_internal/google_analytics.html" . }} From a9523dd39bf931e491750bb832dd13678e0e0c0d Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Sun, 1 May 2022 22:08:14 -0700 Subject: [PATCH 009/122] Add prettier config --- .prettierrc | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..f1bc35a4d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "printWidth": 100, + "quoteProps": "as-needed", + "trailingComma": "all", + "tabWidth": 2 +} From 87144fca212b25093adbf743014d5c0d5b1d9c0d Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Mon, 2 May 2022 08:57:25 -0700 Subject: [PATCH 010/122] Use semi: false for prettier config --- .prettierrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index f1bc35a4d..5788b66f1 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,5 +2,6 @@ "printWidth": 100, "quoteProps": "as-needed", "trailingComma": "all", - "tabWidth": 2 + "tabWidth": 2, + "semi": false } From 5c602ab16f1f5e46bee5f44cec15860f785039ee Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Mon, 2 May 2022 09:04:36 -0700 Subject: [PATCH 011/122] Add clarification comments --- assets/js/graph.js | 6 +++--- assets/js/search.js | 1 + layouts/partials/head.html | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index 939fd99d8..99ecf54ee 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -16,9 +16,8 @@ async function drawGraph( ...new Set(links.flatMap((link) => [link.source, link.target])), ]; - // links is mutated by d3 - // we want to use links later on, so we make a copy and pass - // that one to d3 + // Links is mutated by d3. We want to use links later on, so we make a copy and pass that one to d3 + // Note: shallow cloning does not work because it copies over references from the original array const copyLinks = JSON.parse(JSON.stringify(links)); const neighbours = new Set(); @@ -176,6 +175,7 @@ async function drawGraph( .attr('fill', color) .style('cursor', 'pointer') .on('click', (_, d) => { + // SPA navigation window.navigate( new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, '-')}/`), '.singlePage' diff --git a/assets/js/search.js b/assets/js/search.js index 212b2c730..fcf79177d 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -145,6 +145,7 @@ const removeMarkdown = ( }; const redir = (id, term) => { + // SPA navigation window.navigate( new URL( `${BASE_URL.slice(0, -1)}${id}#:~:text=${encodeURIComponent(term)}/` diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 772153ada..ea67a001c 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -57,9 +57,12 @@ + diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 1dabaf661..37938a556 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -58,6 +58,7 @@ content, })) + {{if $.Site.Data.config.enableSPA}} + {{else}} + + {{end}} {{ template "_internal/google_analytics.html" . }} From 6e6dd4cb0b396ae7ec4f273bccd254bc0f9885d5 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Tue, 3 May 2022 10:57:20 -0400 Subject: [PATCH 019/122] fix: trim trailing slash when calculating popover --- assets/js/popover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/popover.js b/assets/js/popover.js index a4b6852e3..ee0477efd 100644 --- a/assets/js/popover.js +++ b/assets/js/popover.js @@ -13,7 +13,7 @@ function initPopover(baseURL) { links .filter(li => li.dataset.src) .forEach(li => { - const linkDest = content[li.dataset.src.replace(basePath, "")] + const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] if (linkDest) { const popoverElement = `

    ${linkDest.title}

    From 77485b754dbb3d08e437b4157f3eafb5871624b9 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 08:47:42 -0700 Subject: [PATCH 020/122] Fix popover --- assets/js/popover.js | 40 +++++++++++++-------------- assets/js/router.js | 25 +++++++++++++++++ layouts/_default/section.html | 1 - layouts/_default/single.html | 3 +-- layouts/_default/taxonomy.html | 1 - layouts/_default/term.html | 1 - layouts/index.html | 4 +-- layouts/partials/head.html | 49 +++++++++++++++------------------- layouts/partials/popover.html | 7 ----- 9 files changed, 67 insertions(+), 64 deletions(-) create mode 100644 assets/js/router.js delete mode 100644 layouts/partials/popover.html diff --git a/assets/js/popover.js b/assets/js/popover.js index ee0477efd..460c245f7 100644 --- a/assets/js/popover.js +++ b/assets/js/popover.js @@ -1,5 +1,5 @@ function htmlToElement(html) { - const template = document.createElement('template') + const template = document.createElement("template") html = html.trim() template.innerHTML = html return template.content.firstChild @@ -7,29 +7,27 @@ function htmlToElement(html) { function initPopover(baseURL) { 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) - .forEach(li => { - const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] - if (linkDest) { - const popoverElement = `
    + fetchData.then(({ content }) => { + const links = [...document.getElementsByClassName("internal-link")] + links + .filter((li) => li.dataset.src) + .forEach((li) => { + const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] + if (linkDest) { + const popoverElement = `

    ${linkDest.title}

    ${removeMarkdown(linkDest.content).split(" ", 20).join(" ")}...

    ${new Date(linkDest.lastmodified).toLocaleDateString()}

    ` - const el = htmlToElement(popoverElement) - li.appendChild(el) - li.addEventListener("mouseover", () => { - el.classList.add("visible") - }) - li.addEventListener("mouseout", () => { - el.classList.remove("visible") - }) - } - }) - }) + const el = htmlToElement(popoverElement) + li.appendChild(el) + li.addEventListener("mouseover", () => { + el.classList.add("visible") + }) + li.addEventListener("mouseout", () => { + el.classList.remove("visible") + }) + } + }) }) } diff --git a/assets/js/router.js b/assets/js/router.js new file mode 100644 index 000000000..5c874eee6 --- /dev/null +++ b/assets/js/router.js @@ -0,0 +1,25 @@ +import { router, navigate } from "https://unpkg.com/million/dist/router.mjs" + +export const init = (loader) => { + // 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 + window.addEventListener("million:navigate", () => callback(loader)) + window.addEventListener("DOMContentLoaded", () => callback(loader)) +} + +export const callback = (loader) => { + // 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 = "" + + loader() + } + requestAnimationFrame(draw) +} diff --git a/layouts/_default/section.html b/layouts/_default/section.html index 1a4aae058..abdf0b05c 100644 --- a/layouts/_default/section.html +++ b/layouts/_default/section.html @@ -19,7 +19,6 @@ {{partial "contact.html" .}}
    -{{partial "popover.html" .}} diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 88a859c3b..91eda290b 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -22,11 +22,10 @@
  • {{ .LinkTitle | humanize }}
  • {{ end }} - {{partial "toc.html" .}} + {{partial "toc.html" .}} {{partial "textprocessing.html" . }} {{partial "footer.html" .}} - {{partial "popover.html" .}} diff --git a/layouts/_default/taxonomy.html b/layouts/_default/taxonomy.html index b7a45b10f..e0a1e876c 100644 --- a/layouts/_default/taxonomy.html +++ b/layouts/_default/taxonomy.html @@ -28,7 +28,6 @@ {{partial "contact.html" .}} -{{partial "popover.html" .}} diff --git a/layouts/_default/term.html b/layouts/_default/term.html index 16ea85cf8..58f024bcc 100644 --- a/layouts/_default/term.html +++ b/layouts/_default/term.html @@ -19,7 +19,6 @@ {{partial "contact.html" .}} -{{partial "popover.html" .}} diff --git a/layouts/index.html b/layouts/index.html index ee33d7cc8..224c99784 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -13,12 +13,10 @@ {{partial "darkmode.html" .}}
    - {{partial "toc.html" .}} + {{partial "toc.html" .}} {{partial "textprocessing.html" . }}
    {{partial "footer.html" .}} - {{partial "popover.html" .}} - diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 37938a556..60ff78272 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -35,6 +35,10 @@ {{partial "katex.html" .}} + {{ $popover := resources.Get "js/popover.js" | resources.Fingerprint "md5" | + resources.Minify }} + + {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint "md5" | resources.Minify | }} {{$contentIndex := resources.Get @@ -59,36 +63,25 @@ })) {{if $.Site.Data.config.enableSPA}} + {{ $router := resources.Get "js/router.js" | resources.Fingerprint "md5" | + resources.Minify }} {{else}} diff --git a/layouts/partials/popover.html b/layouts/partials/popover.html deleted file mode 100644 index 1d1662282..000000000 --- a/layouts/partials/popover.html +++ /dev/null @@ -1,7 +0,0 @@ -{{if $.Site.Data.config.enableLinkPreview}} -{{ $js := resources.Get "js/popover.js" | resources.Fingerprint "md5" | resources.Minify }} - - -{{end}} \ No newline at end of file From 9c71f07355d8e98478e755875e53596f66c58fa9 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 08:48:35 -0700 Subject: [PATCH 021/122] Enable config for testing --- data/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/config.yaml b/data/config.yaml index afa531c36..2676ac2ac 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -3,7 +3,7 @@ enableToc: true openToc: false enableLinkPreview: true enableLatex: true -enableSPA: false +enableSPA: true description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, Wikilink support, backlinks, local graph, tags, and link previews. From 9d3bbd607687899d173e9087f2782d7460ebee82 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 08:53:18 -0700 Subject: [PATCH 022/122] Fix active node on graph --- assets/js/graph.js | 4 ++-- data/config.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index c5829e927..c32035d83 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -1,5 +1,5 @@ async function drawGraph( - url, + _url, baseUrl, pathColors, depth, @@ -10,7 +10,7 @@ async function drawGraph( const container = document.getElementById('graph-container') const { index, links, content } = await fetchData - const curPage = url.replace(baseUrl, '') + const curPage = window.location.href.replace(baseUrl, '').slice(0, -1) const parseIdsFromLinks = (links) => [ ...new Set(links.flatMap((link) => [link.source, link.target])), diff --git a/data/config.yaml b/data/config.yaml index afa531c36..2676ac2ac 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -3,7 +3,7 @@ enableToc: true openToc: false enableLinkPreview: true enableLatex: true -enableSPA: false +enableSPA: true description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, Wikilink support, backlinks, local graph, tags, and link previews. From 4cca3c1f2df91ba7bb111346447279087e04069a Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 09:04:15 -0700 Subject: [PATCH 023/122] Peg router version --- assets/js/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/router.js b/assets/js/router.js index 5c874eee6..bf7e3c859 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -1,4 +1,4 @@ -import { router, navigate } from "https://unpkg.com/million/dist/router.mjs" +import { router, navigate } from "https://unpkg.com/million@1.8.9-0/dist/router.mjs" export const init = (loader) => { // SPA navigation for access later From 3c660dd9b5f9e1133bc8a1228287508504b7c132 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 09:20:01 -0700 Subject: [PATCH 024/122] Remove unnecessary 'url' param in drawGraph --- assets/js/graph.js | 1 - layouts/partials/head.html | 1 - 2 files changed, 2 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index c32035d83..e92f7db62 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -1,5 +1,4 @@ async function drawGraph( - _url, baseUrl, pathColors, depth, diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 37938a556..93051cb98 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -75,7 +75,6 @@ container.textContent = ""; drawGraph( - {{strings.TrimRight "/" .Page.Permalink}}, {{strings.TrimRight "/" .Site.BaseURL}}, {{$.Site.Data.graphConfig.paths}}, {{$.Site.Data.graphConfig.depth}}, From 32c79a561fa82dbf6537b96e83ab3da2a848b211 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 09:21:44 -0700 Subject: [PATCH 025/122] Remove unnecessary 'url' argument in graph.html --- layouts/partials/graph.html | 1 - 1 file changed, 1 deletion(-) diff --git a/layouts/partials/graph.html b/layouts/partials/graph.html index b8b2f6162..6bc77b648 100644 --- a/layouts/partials/graph.html +++ b/layouts/partials/graph.html @@ -18,7 +18,6 @@ {{else}} From 1a5d158fce648492c48644acfea039261ac1dffa Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 10:38:41 -0700 Subject: [PATCH 030/122] Support active node with other data at end of url --- assets/js/graph.js | 3 ++- assets/js/search.js | 2 +- layouts/partials/graph.html | 10 ---------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index db1cfe2a5..5739acdca 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -9,7 +9,8 @@ async function drawGraph( const container = document.getElementById('graph-container') const { index, links, content } = await fetchData - const curPage = window.location.href.replace(baseUrl, "").replace(/\/$/g, "") + // Use .pathname to remove hashes / searchParams / text fragments + const curPage = window.location.pathname.replace(/\/$/g, "") const parseIdsFromLinks = (links) => [ ...new Set(links.flatMap((link) => [link.source, link.target])), diff --git a/assets/js/search.js b/assets/js/search.js index f124d5829..26ea39adc 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -144,7 +144,7 @@ const removeMarkdown = ( // SPA navigation window.navigate( new URL( - `${BASE_URL}${id}#:~:text=${encodeURIComponent(term)}/` + `${BASE_URL.replace(/\/$/g, "")}${id}#:~:text=${encodeURIComponent(term)}/` ), '.singlePage' ) diff --git a/layouts/partials/graph.html b/layouts/partials/graph.html index 6bc77b648..b9f79763c 100644 --- a/layouts/partials/graph.html +++ b/layouts/partials/graph.html @@ -16,13 +16,3 @@ {{ $js := resources.Get "js/graph.js" | resources.Fingerprint "md5" }} - From aaed5dc1f1849a54869743596a6133548e83392d Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 10:54:39 -0700 Subject: [PATCH 031/122] Support /path root sites --- assets/js/graph.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index 5739acdca..e1bbbebed 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -7,10 +7,13 @@ async function drawGraph( enableZoom ) { const container = document.getElementById('graph-container') - const { index, links, content } = await fetchData + + const rawUrl = new URL(window.location.href); // Use .pathname to remove hashes / searchParams / text fragments - const curPage = window.location.pathname.replace(/\/$/g, "") + const cleanUrl = rawUrl.origin + rawUrl.pathname + + const curPage = cleanUrl.replace(/\/$/g, "").replace(baseUrl, "") const parseIdsFromLinks = (links) => [ ...new Set(links.flatMap((link) => [link.source, link.target])), From 2b5c03c97286e06e94e8a27634678e64473a2ec8 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 3 May 2022 10:55:45 -0700 Subject: [PATCH 032/122] Remove redundant URL construction --- assets/js/graph.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index e1bbbebed..f71e44d37 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -9,9 +9,8 @@ async function drawGraph( const container = document.getElementById('graph-container') const { index, links, content } = await fetchData - const rawUrl = new URL(window.location.href); // Use .pathname to remove hashes / searchParams / text fragments - const cleanUrl = rawUrl.origin + rawUrl.pathname + const cleanUrl = window.location.origin + window.location.pathname const curPage = cleanUrl.replace(/\/$/g, "").replace(baseUrl, "") From b4ff12ca0b1b5179c20a1ea57f182caa703b0826 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Wed, 4 May 2022 08:10:59 -0700 Subject: [PATCH 033/122] Fix latex --- .pnpm-debug.log | 14 ++++++++++++++ layouts/partials/head.html | 9 +++++++++ layouts/partials/katex.html | 11 ----------- 3 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 .pnpm-debug.log diff --git a/.pnpm-debug.log b/.pnpm-debug.log new file mode 100644 index 000000000..ce5adc898 --- /dev/null +++ b/.pnpm-debug.log @@ -0,0 +1,14 @@ +{ + "0 debug pnpm:scope": { + "selected": 1 + }, + "1 error pnpm": { + "code": "ERR_PNPM_NO_SCRIPT", + "err": { + "name": "pnpm", + "message": "Missing script: dev", + "code": "ERR_PNPM_NO_SCRIPT", + "stack": "pnpm: Missing script: dev\n at Object.handler (/opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:170956:15)\n at async /opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:175391:21\n at async run (/opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:175365:34)\n at async runPnpm (/opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:175583:5)\n at async /opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:175575:7" + } + } +} \ No newline at end of file diff --git a/layouts/partials/head.html b/layouts/partials/head.html index b917afbc4..097cae79c 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -87,6 +87,15 @@ {{if $.Site.Data.config.enableLinkPreview}} initPopover({{strings.TrimRight "/" .Site.BaseURL }}) {{end}} + {{if $.Site.Data.config.enableLatex}} + renderMathInElement(document.body, { + delimiters: [ + {left: '$$', right: '$$', display: true}, + {left: '$', right: '$', display: false}, + ], + throwOnError : false + }); + {{end}} }; attachSPARouting(draw); diff --git a/layouts/partials/katex.html b/layouts/partials/katex.html index e11c4f14e..756ef779e 100644 --- a/layouts/partials/katex.html +++ b/layouts/partials/katex.html @@ -2,15 +2,4 @@ - {{end}} From 7b3696b877c33f8dc605be1f4f4a688fe0df5b84 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Wed, 4 May 2022 08:39:25 -0700 Subject: [PATCH 034/122] Remove pnpm debug log --- .pnpm-debug.log | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .pnpm-debug.log diff --git a/.pnpm-debug.log b/.pnpm-debug.log deleted file mode 100644 index ce5adc898..000000000 --- a/.pnpm-debug.log +++ /dev/null @@ -1,14 +0,0 @@ -{ - "0 debug pnpm:scope": { - "selected": 1 - }, - "1 error pnpm": { - "code": "ERR_PNPM_NO_SCRIPT", - "err": { - "name": "pnpm", - "message": "Missing script: dev", - "code": "ERR_PNPM_NO_SCRIPT", - "stack": "pnpm: Missing script: dev\n at Object.handler (/opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:170956:15)\n at async /opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:175391:21\n at async run (/opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:175365:34)\n at async runPnpm (/opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:175583:5)\n at async /opt/homebrew/lib/node_modules/pnpm/dist/pnpm.cjs:175575:7" - } - } -} \ No newline at end of file From cea0f3eb743b26db0d5297ab10e229617585fe0c Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 5 May 2022 00:58:50 -0400 Subject: [PATCH 035/122] feat: contextual backlinks (closes #106) --- .github/workflows/deploy.yaml | 2 +- assets/js/popover.js | 28 +++++++-- assets/js/search.js | 104 +++++++++++++++++--------------- assets/styles/base.scss | 12 ++-- data/config.yaml | 1 + layouts/partials/backlinks.html | 15 +++-- layouts/partials/popover.html | 5 +- 7 files changed, 101 insertions(+), 66 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index ee51d3eeb..8334ea2ee 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -14,7 +14,7 @@ jobs: fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Build Link Index - uses: jackyzha0/hugo-obsidian@v2.12 + uses: jackyzha0/hugo-obsidian@v2.13 with: index: true input: content diff --git a/assets/js/popover.js b/assets/js/popover.js index ee0477efd..ea01156bb 100644 --- a/assets/js/popover.js +++ b/assets/js/popover.js @@ -5,19 +5,20 @@ function htmlToElement(html) { return template.content.firstChild } -function initPopover(baseURL) { +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) + .filter(li => li.dataset.src || (li.dataset.idx && useContextualBacklinks)) .forEach(li => { - const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] - if (linkDest) { + if (li.dataset.ctx) { + console.log(li.dataset.ctx) + const linkDest = content[li.dataset.src] const popoverElement = `

    ${linkDest.title}

    -

    ${removeMarkdown(linkDest.content).split(" ", 20).join(" ")}...

    +

    ${highlight(removeMarkdown(linkDest.content), li.dataset.ctx)}...

    ${new Date(linkDest.lastmodified).toLocaleDateString()}

    ` const el = htmlToElement(popoverElement) @@ -28,6 +29,23 @@ function initPopover(baseURL) { li.addEventListener("mouseout", () => { el.classList.remove("visible") }) + } else { + const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] + if (linkDest) { + const popoverElement = `
    +

    ${linkDest.title}

    +

    ${removeMarkdown(linkDest.content).split(" ", 20).join(" ")}...

    +

    ${new Date(linkDest.lastmodified).toLocaleDateString()}

    +
    ` + const el = htmlToElement(popoverElement) + li.appendChild(el) + li.addEventListener("mouseover", () => { + el.classList.add("visible") + }) + li.addEventListener("mouseout", () => { + el.classList.remove("visible") + }) + } } }) }) diff --git a/assets/js/search.js b/assets/js/search.js index f124d5829..c5e293cc1 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -52,9 +52,65 @@ const removeMarkdown = ( return markdown } return output -}; +} // ----- +const highlight = (content, term) => { + const highlightWindow = 20 + + // try to find direct match first + const directMatchIdx = content.indexOf(term) + if (directMatchIdx !== -1) { + const h = highlightWindow / 2 + const before = content.substring(0, directMatchIdx).split(" ").slice(-h) + const after = content.substring(directMatchIdx + term.length, content.length - 1).split(" ").slice(0, h) + return (before.length == h ? `...${before.join(" ")}` : before.join(" ")) + `${term}` + after.join(" ") + } + + const tokenizedTerm = term.split(/\s+/).filter((t) => t !== '') + const splitText = content.split(/\s+/).filter((t) => t !== '') + const includesCheck = (token) => + tokenizedTerm.some((term) => + token.toLowerCase().startsWith(term.toLowerCase()) + ) + + const occurrencesIndices = splitText.map(includesCheck) + + // calculate best index + let bestSum = 0 + let bestIndex = 0 + for ( + let i = 0; + i < Math.max(occurrencesIndices.length - highlightWindow, 0); + i++ + ) { + const window = occurrencesIndices.slice(i, i + highlightWindow) + const windowSum = window.reduce((total, cur) => total + cur, 0) + if (windowSum >= bestSum) { + bestSum = windowSum + bestIndex = i + } + } + + const startIndex = Math.max(bestIndex - highlightWindow, 0) + const endIndex = Math.min( + startIndex + 2 * highlightWindow, + splitText.length + ) + const mappedText = splitText + .slice(startIndex, endIndex) + .map((token) => { + if (includesCheck(token)) { + return `${token}` + } + return token + }) + .join(' ') + .replaceAll(' ', ' ') + return `${startIndex === 0 ? '' : '...'}${mappedText}${endIndex === splitText.length ? '' : '...' + }` +}; + (async function() { const encoder = (str) => str.toLowerCase().split(/([^a-z]|[^\x00-\x7F])+/) const contentIndex = new FlexSearch.Document({ @@ -84,52 +140,6 @@ const removeMarkdown = ( }) } - const highlight = (content, term) => { - const highlightWindow = 20 - const tokenizedTerm = term.split(/\s+/).filter((t) => t !== '') - const splitText = content.split(/\s+/).filter((t) => t !== '') - const includesCheck = (token) => - tokenizedTerm.some((term) => - token.toLowerCase().startsWith(term.toLowerCase()) - ) - - const occurrencesIndices = splitText.map(includesCheck) - - // calculate best index - let bestSum = 0 - let bestIndex = 0 - for ( - let i = 0; - i < Math.max(occurrencesIndices.length - highlightWindow, 0); - i++ - ) { - const window = occurrencesIndices.slice(i, i + highlightWindow) - const windowSum = window.reduce((total, cur) => total + cur, 0) - if (windowSum >= bestSum) { - bestSum = windowSum - bestIndex = i - } - } - - const startIndex = Math.max(bestIndex - highlightWindow, 0) - const endIndex = Math.min( - startIndex + 2 * highlightWindow, - splitText.length - ) - const mappedText = splitText - .slice(startIndex, endIndex) - .map((token) => { - if (includesCheck(token)) { - return `${token}` - } - return token - }) - .join(' ') - .replaceAll(' ', ' ') - return `${startIndex === 0 ? '' : '...'}${mappedText}${endIndex === splitText.length ? '' : '...' - }` - } - const resultToHTML = ({ url, title, content, term }) => { const text = removeMarkdown(content) const resultTitle = highlight(title, term) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 9bbd933a2..078747099 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -478,17 +478,17 @@ header { & > h3, & > p { margin: 0; } - - & .search-highlight { - background-color: #afbfc966; - padding: 0.05em 0.2em; - border-radius: 3px; - } } } } } +.search-highlight { + background-color: #afbfc966; + padding: 0.05em 0.2em; + border-radius: 3px; +} + .section-ul { list-style: none; padding-left: 0; diff --git a/data/config.yaml b/data/config.yaml index afa531c36..ccf38eb71 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -4,6 +4,7 @@ openToc: false enableLinkPreview: true enableLatex: true enableSPA: false +enableContextualBacklinks: true description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, Wikilink support, backlinks, local graph, tags, and link previews. diff --git a/layouts/partials/backlinks.html b/layouts/partials/backlinks.html index e42351ad5..23c9091a5 100644 --- a/layouts/partials/backlinks.html +++ b/layouts/partials/backlinks.html @@ -7,13 +7,18 @@ {{$inbound := index $linkIndex.index.backlinks $curPage}} {{$contentTable := getJSON "/assets/indices/contentIndex.json"}} {{if $inbound}} - {{$cleanedInbound := apply (apply $inbound "index" "." "source") "replace" "." " " "-"}} - {{- range $cleanedInbound | uniq -}} - {{$l := printf "%s%s/" $host .}} + {{$backlinks := dict "SENTINEL" "SENTINEL"}} + {{range $k, $v := $inbound}} + {{$cleanedInbound := replace $v.source " " "-"}} + {{$ctx := $v.text}} + {{$backlinks = merge $backlinks (dict $cleanedInbound $ctx)}} + {{end}} + {{- range $lnk, $ctx := $backlinks -}} + {{$l := printf "%s%s/" $host $lnk}} {{$l = cond (eq $l "//") "/" $l}} - {{with (index $contentTable .)}} + {{with (index $contentTable $lnk)}}
  • - {{index (index . "title")}} + {{index (index . "title")}}
  • {{end}} {{- end -}} diff --git a/layouts/partials/popover.html b/layouts/partials/popover.html index 1d1662282..ba1fd0373 100644 --- a/layouts/partials/popover.html +++ b/layouts/partials/popover.html @@ -2,6 +2,7 @@ {{ $js := resources.Get "js/popover.js" | resources.Fingerprint "md5" | resources.Minify }} -{{end}} \ No newline at end of file +{{end}} From b21b27d1d3d68bfb4d285f39122a154fceefb9ab Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 5 May 2022 20:30:55 -0400 Subject: [PATCH 036/122] fix: clean wikilinks and render latex in popover --- assets/js/popover.js | 41 +++++++++++++++++++-------------- assets/js/search.js | 1 + layouts/partials/head.html | 6 ++++- layouts/partials/page-list.html | 2 +- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/assets/js/popover.js b/assets/js/popover.js index 9270b8ae0..5fb2244ad 100644 --- a/assets/js/popover.js +++ b/assets/js/popover.js @@ -5,13 +5,14 @@ function htmlToElement(html) { return template.content.firstChild } -function initPopover(baseURL, useContextualBacklinks) { +function initPopover(baseURL, useContextualBacklinks, renderLatex) { const basePath = baseURL.replace(window.location.origin, "") fetchData.then(({ content }) => { const links = [...document.getElementsByClassName("internal-link")] links .filter(li => li.dataset.src || (li.dataset.idx && useContextualBacklinks)) .forEach(li => { + var el if (li.dataset.ctx) { const linkDest = content[li.dataset.src] const popoverElement = `
    @@ -19,32 +20,38 @@ function initPopover(baseURL, useContextualBacklinks) {

    ${highlight(removeMarkdown(linkDest.content), li.dataset.ctx)}...

    ${new Date(linkDest.lastmodified).toLocaleDateString()}

    ` - const el = htmlToElement(popoverElement) - li.appendChild(el) - li.addEventListener("mouseover", () => { - el.classList.add("visible") - }) - li.addEventListener("mouseout", () => { - el.classList.remove("visible") - }) + el = htmlToElement(popoverElement) } else { const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] + console.log(linkDest.content) if (linkDest) { const popoverElement = `

    ${linkDest.title}

    ${removeMarkdown(linkDest.content).split(" ", 20).join(" ")}...

    ${new Date(linkDest.lastmodified).toLocaleDateString()}

    ` - const el = htmlToElement(popoverElement) - li.appendChild(el) - li.addEventListener("mouseover", () => { - el.classList.add("visible") - }) - li.addEventListener("mouseout", () => { - el.classList.remove("visible") - }) + el = htmlToElement(popoverElement) } } + li.appendChild(el) + if (renderLatex) { + renderMathInElement(el, { + delimiters: [ + { left: '$$', right: '$$', display: false }, + { left: '$', right: '$', display: false }, + { left: '\\(', right: '\\)', display: false }, + { left: '\\[', right: '\\]', display: false } + ], + throwOnError: false + }) + } + li.addEventListener("mouseover", () => { + el.classList.add("visible") + }) + li.addEventListener("mouseout", () => { + el.classList.remove("visible") + }) + }) }) } diff --git a/assets/js/search.js b/assets/js/search.js index 975eaa657..195a40be5 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -39,6 +39,7 @@ const removeMarkdown = ( .replace(/\s{0,2}\[.*?\]: .*?$/g, '') .replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, options.useImgAltText ? '$1' : '') .replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1') + .replace(/!?\[\[\S[^\[\]\|]*(?:\|([^\[\]]*))?\S\]\]/g, '$1') .replace(/^\s{0,3}>\s?/g, '') .replace(/(^|\n)\s{0,3}>\s?/g, '\n\n') .replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '') diff --git a/layouts/partials/head.html b/layouts/partials/head.html index a8d947e46..a5f23da30 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -85,7 +85,11 @@ ); {{if $.Site.Data.config.enableLinkPreview}} - initPopover({{strings.TrimRight "/" .Site.BaseURL }}, {{$.Site.Data.config.enableContextualBacklinks}}) + initPopover( + {{strings.TrimRight "/" .Site.BaseURL }}, + {{$.Site.Data.config.enableContextualBacklinks}}, + {{$.Site.Data.config.enableLatex}} + ) {{end}} {{if $.Site.Data.config.enableLatex}} renderMathInElement(document.body, { diff --git a/layouts/partials/page-list.html b/layouts/partials/page-list.html index bdfcd59ce..6c2249baf 100644 --- a/layouts/partials/page-list.html +++ b/layouts/partials/page-list.html @@ -12,4 +12,4 @@ {{- end -}} - \ No newline at end of file + From e302f6c423136d1dbdfda48c2b241e62bb5654e7 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 5 May 2022 20:35:32 -0400 Subject: [PATCH 037/122] fix: more generic style to match bad nesting generated by popover interp --- assets/styles/base.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 078747099..6378f900e 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -441,7 +441,7 @@ header { } & > #results-container { - & > .result-card { + & .result-card { padding: 1em; cursor: pointer; transition: background 0.2s ease; From ed9a8efd1ff4ee569fa4256e044151670abaea82 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 5 May 2022 21:11:23 -0400 Subject: [PATCH 038/122] fix inline link highlighting, safer latex render --- assets/js/popover.js | 37 +++++++++++++++++++------------------ assets/js/search.js | 4 ++-- assets/styles/base.scss | 2 +- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/assets/js/popover.js b/assets/js/popover.js index 5fb2244ad..494cd84e1 100644 --- a/assets/js/popover.js +++ b/assets/js/popover.js @@ -23,7 +23,6 @@ function initPopover(baseURL, useContextualBacklinks, renderLatex) { el = htmlToElement(popoverElement) } else { const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] - console.log(linkDest.content) if (linkDest) { const popoverElement = `

    ${linkDest.title}

    @@ -33,25 +32,27 @@ function initPopover(baseURL, useContextualBacklinks, renderLatex) { el = htmlToElement(popoverElement) } } - li.appendChild(el) - if (renderLatex) { - renderMathInElement(el, { - delimiters: [ - { left: '$$', right: '$$', display: false }, - { left: '$', right: '$', display: false }, - { left: '\\(', right: '\\)', display: false }, - { left: '\\[', right: '\\]', display: false } - ], - throwOnError: false + + if (el) { + li.appendChild(el) + if (renderLatex) { + renderMathInElement(el, { + delimiters: [ + { left: '$$', right: '$$', display: false }, + { left: '$', right: '$', display: false }, + { left: '\\(', right: '\\)', display: false }, + { left: '\\[', right: '\\]', display: false } + ], + throwOnError: false + }) + } + li.addEventListener("mouseover", () => { + el.classList.add("visible") + }) + li.addEventListener("mouseout", () => { + el.classList.remove("visible") }) } - li.addEventListener("mouseover", () => { - el.classList.add("visible") - }) - li.addEventListener("mouseout", () => { - el.classList.remove("visible") - }) - }) }) } diff --git a/assets/js/search.js b/assets/js/search.js index 195a40be5..bb94cd30b 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -38,8 +38,8 @@ const removeMarkdown = ( .replace(/(#{1,6})\s+(.+)\1?/g, '$2') .replace(/\s{0,2}\[.*?\]: .*?$/g, '') .replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, options.useImgAltText ? '$1' : '') - .replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1') - .replace(/!?\[\[\S[^\[\]\|]*(?:\|([^\[\]]*))?\S\]\]/g, '$1') + .replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1') + .replace(/!?\[\[\S[^\[\]\|]*(?:\|([^\[\]]*))?\S\]\]/g, '$1') .replace(/^\s{0,3}>\s?/g, '') .replace(/(^|\n)\s{0,3}>\s?/g, '\n\n') .replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '') diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 6378f900e..1b9b936e3 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -569,7 +569,7 @@ header { font-size: 0.8rem; } - & > p { + & > p, & > a { margin: 0; font-weight: 400; user-select: none; From 0b6711c2185abbde7e95125b672ee8b5d827cb8b Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 14 May 2022 16:47:50 -0400 Subject: [PATCH 039/122] fix: tag boxes overlapping for content with many tags (closes #130) --- assets/styles/base.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 1b9b936e3..de866fdbb 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -186,6 +186,7 @@ article { & > li { display: inline-block; + margin: 0.4em 0; } & > li > a { border-radius: 8px; From 0439c163a03fc50487fbe1cbfc09dc38af7ed2f2 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Fri, 20 May 2022 16:50:56 -0400 Subject: [PATCH 040/122] fix: js not executing if spa disabled --- layouts/partials/head.html | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index a5f23da30..a49800be5 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -61,13 +61,7 @@ links, content, })) - - {{if $.Site.Data.config.enableSPA}} - {{ $router := resources.Get "js/router.js" | resources.Fingerprint "md5" | - resources.Minify }} - + {{if $.Site.Data.config.enableSPA}} + {{ $router := resources.Get "js/router.js" | resources.Fingerprint "md5" | + resources.Minify }} + {{else}} - + {{end}} {{ template "_internal/google_analytics.html" . }} From 0293c122177bf8c595cda8b4dfb513d90b1e6b03 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Mon, 23 May 2022 22:25:13 -0700 Subject: [PATCH 041/122] feat: recent posts section/partial --- assets/styles/base.scss | 61 +++++++++++++++++---------------- data/config.yaml | 1 + layouts/index.html | 3 ++ layouts/partials/page-list.html | 6 ++++ layouts/partials/recent.html | 12 +++++++ 5 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 layouts/partials/recent.html diff --git a/assets/styles/base.scss b/assets/styles/base.scss index de866fdbb..1c353f338 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -171,35 +171,6 @@ article { opacity: 0.7; } - & > .tags { - list-style: none; - padding-left: 0; - - & .meta { - & > h1 { - margin: 0; - } - & > p { - margin: 0; - } - } - - & > li { - display: inline-block; - margin: 0.4em 0; - } - & > li > a { - border-radius: 8px; - border: var(--outlinegray) 1px solid; - padding: 0.2em 0.5em; - &::before { - content: "#"; - margin-right: 0.3em; - color: var(--outlinegray); - } - } - } - & a { font-family: Source Sans Pro; font-weight: 600; @@ -223,6 +194,36 @@ article { } } +.tags { + list-style: none; + padding-left: 0; + + & .meta { + & > h1 { + margin: 0; + } + & > p { + margin: 0; + } + } + + & > li { + display: inline-block; + margin: 0.4em 0; + } + + & > li > a { + border-radius: 8px; + border: var(--outlinegray) 1px solid; + padding: 0.2em 0.5em; + &::before { + content: "#"; + margin-right: 0.3em; + color: var(--outlinegray); + } + } +} + .backlinks a { font-weight: 600; font-size: 0.9rem; @@ -590,3 +591,5 @@ header { padding: 0 1em; } } + + diff --git a/data/config.yaml b/data/config.yaml index 2b606e74e..b79ad5721 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -5,6 +5,7 @@ enableLinkPreview: true enableLatex: true enableSPA: true enableContextualBacklinks: true +enableRecentNotes: false description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, Wikilink support, backlinks, local graph, tags, and link previews. diff --git a/layouts/index.html b/layouts/index.html index 224c99784..8d1ffbd4f 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -15,6 +15,9 @@
    {{partial "toc.html" .}} {{partial "textprocessing.html" . }} + {{if $.Site.Data.config.enableRecentNotes}} + {{partial "recent.html" . }} + {{end}}
    {{partial "footer.html" .}}
    diff --git a/layouts/partials/page-list.html b/layouts/partials/page-list.html index 6c2249baf..e51c5ddab 100644 --- a/layouts/partials/page-list.html +++ b/layouts/partials/page-list.html @@ -4,11 +4,17 @@

    {{- .Title -}}

    +

    {{- .Summary -}}{{if .Truncated}}...{{end}}

    {{ .ReadingTime }} minute read. Last updated {{if ne .Date .Lastmod}}{{ .Lastmod.Format "January 2, 2006" }}{{else}}Unknown{{end}}

    +
    {{- end -}} diff --git a/layouts/partials/recent.html b/layouts/partials/recent.html new file mode 100644 index 000000000..e3926c243 --- /dev/null +++ b/layouts/partials/recent.html @@ -0,0 +1,12 @@ +
    +

    Recent Notes

    + + {{$notes := .Site.RegularPages}} + {{partial "page-list.html" (first 3 $notes)}} +
    + From bd316d8249f096c4d5616d682f142f49d4ca914f Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 08:39:44 -0700 Subject: [PATCH 042/122] Bump million to 1.9.2 --- assets/js/router.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/assets/js/router.js b/assets/js/router.js index 81c25ac1c..b70aac2d6 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -1,12 +1,16 @@ -import { router, navigate } from "https://unpkg.com/million@1.8.9-0/dist/router.mjs" +import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.2/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 + // Attach SPA functions to the global Million namespace + window.Million = { + router, + navigate, + reload, + prefetch, + }; 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)) + reload(draw) window.addEventListener("DOMContentLoaded", () => requestAnimationFrame(draw)) } From efb6c7845f0a2743dd07b81f1d03b03d058ede0d Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 08:40:00 -0700 Subject: [PATCH 043/122] Add prefetch to graph --- assets/js/graph.js | 205 +++++++++++++++---------------------- assets/js/search.js | 2 +- layouts/partials/head.html | 2 +- 3 files changed, 87 insertions(+), 122 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index f71e44d37..c7634cf3e 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -1,12 +1,5 @@ -async function drawGraph( - baseUrl, - pathColors, - depth, - enableDrag, - enableLegend, - enableZoom -) { - const container = document.getElementById('graph-container') +async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, enableZoom) { + const container = document.getElementById("graph-container") const { index, links, content } = await fetchData // Use .pathname to remove hashes / searchParams / text fragments @@ -23,22 +16,19 @@ async function drawGraph( const copyLinks = JSON.parse(JSON.stringify(links)) const neighbours = new Set() - const wl = [curPage || '/', '__SENTINEL'] + const wl = [curPage || "/", "__SENTINEL"] if (depth >= 0) { while (depth >= 0 && wl.length > 0) { // compute neighbours const cur = wl.shift() - if (cur === '__SENTINEL') { + if (cur === "__SENTINEL") { depth-- - wl.push('__SENTINEL') + wl.push("__SENTINEL") } else { neighbours.add(cur) const outgoing = index.links[cur] || [] const incoming = index.backlinks[cur] || [] - wl.push( - ...outgoing.map((l) => l.target), - ...incoming.map((l) => l.source) - ) + wl.push(...outgoing.map((l) => l.target), ...incoming.map((l) => l.source)) } } } else { @@ -47,14 +37,12 @@ async function drawGraph( const data = { nodes: [...neighbours].map((id) => ({ id })), - links: copyLinks.filter( - (l) => neighbours.has(l.source) && neighbours.has(l.target) - ), + links: copyLinks.filter((l) => neighbours.has(l.source) && neighbours.has(l.target)), } const color = (d) => { - if (d.id === curPage || (d.id === '/' && curPage === '')) { - return 'var(--g-node-active)' + if (d.id === curPage || (d.id === "/" && curPage === "")) { + return "var(--g-node-active)" } for (const pathColor of pathColors) { @@ -65,7 +53,7 @@ async function drawGraph( } } - return 'var(--g-node)' + return "var(--g-node)" } const drag = (simulation) => { @@ -86,12 +74,12 @@ async function drawGraph( d.fy = null } - const noop = () => { } + const noop = () => {} return d3 .drag() - .on('start', enableDrag ? dragstarted : noop) - .on('drag', enableDrag ? dragged : noop) - .on('end', enableDrag ? dragended : noop) + .on("start", enableDrag ? dragstarted : noop) + .on("drag", enableDrag ? dragged : noop) + .on("end", enableDrag ? dragended : noop) } const height = Math.max(container.offsetHeight, 250) @@ -99,67 +87,58 @@ async function drawGraph( const simulation = d3 .forceSimulation(data.nodes) - .force('charge', d3.forceManyBody().strength(-30)) + .force("charge", d3.forceManyBody().strength(-30)) .force( - 'link', + "link", d3 .forceLink(data.links) .id((d) => d.id) - .distance(40) + .distance(40), ) - .force('center', d3.forceCenter()) + .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]) + .select("#graph-container") + .append("svg") + .attr("width", width) + .attr("height", height) + .attr("viewBox", [-width / 2, -height / 2, width, height]) if (enableLegend) { - const legend = [ - { Current: 'var(--g-node-active)' }, - { Note: 'var(--g-node)' }, - ...pathColors, - ] + 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) + .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)) + .append("text") + .attr("x", -width / 2 + 40) + .attr("y", height / 2 - 30 * (i + 1)) .text(key) - .style('font-size', '15px') - .attr('alignment-baseline', 'middle') + .style("font-size", "15px") + .attr("alignment-baseline", "middle") }) } // draw links between nodes const link = svg - .append('g') - .selectAll('line') + .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) + .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') + const graphNode = svg.append("g").selectAll("g").data(data.nodes).enter().append("g") // calculate radius const nodeRadius = (d) => { @@ -170,82 +149,68 @@ async function drawGraph( // draw individual nodes const node = graphNode - .append('circle') - .attr('class', 'node') - .attr('id', (d) => d.id) - .attr('r', nodeRadius) - .attr('fill', color) - .style('cursor', 'pointer') - .on('click', (_, d) => { + .append("circle") + .attr("class", "node") + .attr("id", (d) => d.id) + .attr("r", nodeRadius) + .attr("fill", color) + .style("cursor", "pointer") + .on("click", (_, d) => { // SPA navigation - window.navigate( - new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, '-')}/`), - '.singlePage' - ) + window.Million.navigate(new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, "-")}/`), ".singlePage") }) - .on('mouseover', function(_, d) { - d3.selectAll('.node') - .transition() - .duration(100) - .attr('fill', 'var(--g-node-inactive)') + .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 neighbourNodes = d3.selectAll(".node").filter((d) => neighbours.includes(d.id)) const currentId = d.id + window.Million.prefetch(new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, "-")}/`)) const linkNodes = d3 - .selectAll('.link') + .selectAll(".link") .filter((d) => d.source.id === currentId || d.target.id === currentId) // highlight neighbour nodes - neighbourNodes.transition().duration(200).attr('fill', color) + neighbourNodes.transition().duration(200).attr("fill", color) // highlight links - linkNodes - .transition() - .duration(200) - .attr('stroke', 'var(--g-link-active)') + linkNodes.transition().duration(200).attr("stroke", "var(--g-link-active)") // show text for self d3.select(this.parentNode) .raise() - .select('text') + .select("text") .transition() .duration(200) - .style('opacity', 1) + .style("opacity", 1) }) - .on('mouseleave', function(_, d) { - d3.selectAll('.node').transition().duration(200).attr('fill', color) + .on("mouseleave", function (_, d) { + d3.selectAll(".node").transition().duration(200).attr("fill", color) const currentId = d.id const linkNodes = d3 - .selectAll('.link') + .selectAll(".link") .filter((d) => d.source.id === currentId || d.target.id === currentId) - linkNodes.transition().duration(200).attr('stroke', 'var(--g-link)') + linkNodes.transition().duration(200).attr("stroke", "var(--g-link)") - d3.select(this.parentNode) - .select('text') - .transition() - .duration(200) - .style('opacity', 0) + d3.select(this.parentNode).select("text").transition().duration(200).style("opacity", 0) }) .call(drag(simulation)) // draw labels const labels = graphNode - .append('text') - .attr('dx', 0) - .attr('dy', (d) => nodeRadius(d) + 8 + 'px') - .attr('text-anchor', 'middle') - .text((d) => content[d.id]?.title || d.id.replace('-', ' ')) - .style('opacity', 0) - .style('pointer-events', 'none') - .style('font-size', '0.4em') + .append("text") + .attr("dx", 0) + .attr("dy", (d) => nodeRadius(d) + 8 + "px") + .attr("text-anchor", "middle") + .text((d) => content[d.id]?.title || d.id.replace("-", " ")) + .style("opacity", 0) + .style("pointer-events", "none") + .style("font-size", "0.4em") .raise() .call(drag(simulation)) @@ -260,24 +225,24 @@ async function drawGraph( [width, height], ]) .scaleExtent([0.25, 4]) - .on('zoom', ({ transform }) => { - link.attr('transform', transform) - node.attr('transform', transform) + .on("zoom", ({ transform }) => { + link.attr("transform", transform) + node.attr("transform", transform) const scale = transform.k const scaledOpacity = Math.max((scale - 1) / 3.75, 0) - labels.attr('transform', transform).style('opacity', scaledOpacity) - }) + labels.attr("transform", transform).style("opacity", scaledOpacity) + }), ) } // progress the simulation - simulation.on('tick', () => { + 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) + .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) }) } diff --git a/assets/js/search.js b/assets/js/search.js index bb94cd30b..ee0064715 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -153,7 +153,7 @@ const highlight = (content, term) => { const redir = (id, term) => { // SPA navigation - window.navigate( + window.Million.navigate( new URL( `${BASE_URL.replace(/\/$/g, "")}${id}#:~:text=${encodeURIComponent(term)}/` ), diff --git a/layouts/partials/head.html b/layouts/partials/head.html index a49800be5..b65bb8430 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -107,7 +107,7 @@ {{else}} {{end}} From bc32bbeaed10eac3094fcaa899ca626dc8e56771 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 09:02:01 -0700 Subject: [PATCH 044/122] Bump milliomn to 1.9.3 --- assets/js/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/router.js b/assets/js/router.js index b70aac2d6..dff17413a 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -1,4 +1,4 @@ -import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.2/dist/router.mjs" +import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.3/dist/router.mjs" export const attachSPARouting = (draw) => { // Attach SPA functions to the global Million namespace From e0fd9570d746cb2aa270dbe64dae038fc02bdbac Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 09:49:28 -0700 Subject: [PATCH 045/122] Bump million to 1.9.4 --- assets/js/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/router.js b/assets/js/router.js index dff17413a..3cd335002 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -1,4 +1,4 @@ -import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.3/dist/router.mjs" +import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.4/dist/router.mjs" export const attachSPARouting = (draw) => { // Attach SPA functions to the global Million namespace From 683cb53cbd4d581a061b64a26da54285ef479e19 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 13:19:19 -0700 Subject: [PATCH 046/122] Bump million to 1.9.5 --- assets/js/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/router.js b/assets/js/router.js index 3cd335002..278ed565c 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -1,4 +1,4 @@ -import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.4/dist/router.mjs" +import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.5/dist/router.mjs" export const attachSPARouting = (draw) => { // Attach SPA functions to the global Million namespace From 44984cdaf4dfca8c25e9b73066ee22c775ed6d2e Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 13:27:13 -0700 Subject: [PATCH 047/122] Add support for progress bar --- assets/styles/custom.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/styles/custom.scss b/assets/styles/custom.scss index 612b80a61..0a23ffca3 100644 --- a/assets/styles/custom.scss +++ b/assets/styles/custom.scss @@ -9,6 +9,7 @@ --gray: #4e4e4e; --lightgray: #f0f0f0; --outlinegray: #dadada; + --million-progress-bar-color: var(--secondary); } [saved-theme="dark"] { @@ -21,4 +22,5 @@ --gray: #d4d4d4 !important; --lightgray: #292633 !important; --outlinegray: #343434 !important; + --million-progress-bar-color: var(--secondary) !important; } \ No newline at end of file From 159deabfe160c7570679269873f18776cb586437 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 16:14:17 -0700 Subject: [PATCH 048/122] Bump to 1.9.6 --- assets/js/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/router.js b/assets/js/router.js index 278ed565c..787cd7653 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -1,4 +1,4 @@ -import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.5/dist/router.mjs" +import { router, navigate, reload, prefetch } from "https://unpkg.com/million@1.9.6/dist/router.mjs" export const attachSPARouting = (draw) => { // Attach SPA functions to the global Million namespace From ae240ff82cd8de66c28b1608e72db6ed397cab13 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 18:31:36 -0700 Subject: [PATCH 049/122] Remove redundant CSS rule --- assets/styles/custom.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/styles/custom.scss b/assets/styles/custom.scss index 0a23ffca3..54dbacef6 100644 --- a/assets/styles/custom.scss +++ b/assets/styles/custom.scss @@ -22,5 +22,4 @@ --gray: #d4d4d4 !important; --lightgray: #292633 !important; --outlinegray: #343434 !important; - --million-progress-bar-color: var(--secondary) !important; } \ No newline at end of file From 8aba612a0013e84f0b3f9d60863c02ad1b0bfd6e Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 18:42:01 -0700 Subject: [PATCH 050/122] Fix non-spa fallback --- layouts/partials/head.html | 58 +++++++++++++++----------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index b65bb8430..2da259d46 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -5,45 +5,31 @@ name="description" content="{{if .IsHome}}{{$.Site.Data.config.description}}{{else}}{{.Summary}}{{end}}" /> - - {{ if .Title }}{{ .Title }}{{ else }}{{ $.Site.Data.config.page_title }}{{ - end }} - + {{ if .Title }}{{ .Title }}{{ else }}{{ $.Site.Data.config.page_title }}{{ end }} - + - {{$sass := resources.Match "styles/[!_]*.scss" }} - {{$css := slice }} - {{range $sass}} - {{$scss := . | resources.ToCSS (dict "outputStyle" "compressed") }} - {{$css = $css | append $scss}} - {{end}} - {{$finalCss := $css | resources.Concat "styles.css" | resources.Fingerprint "md5" | resources.Minify }} + {{$sass := resources.Match "styles/[!_]*.scss" }} {{$css := slice }} {{range $sass}} {{$scss := . + | resources.ToCSS (dict "outputStyle" "compressed") }} {{$css = $css | append $scss}} {{end}} + {{$finalCss := $css | resources.Concat "styles.css" | resources.Fingerprint "md5" | + resources.Minify }} - {{ $darkMode := resources.Get "js/darkmode.js" | resources.Fingerprint "md5" | - resources.Minify }} + {{ $darkMode := resources.Get "js/darkmode.js" | resources.Fingerprint "md5" | resources.Minify }} - {{partial "katex.html" .}} - - {{ $popover := resources.Get "js/popover.js" | resources.Fingerprint "md5" | - resources.Minify }} + {{partial "katex.html" .}} {{ $popover := resources.Get "js/popover.js" | resources.Fingerprint + "md5" | resources.Minify }} - {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint - "md5" | resources.Minify | }} {{$contentIndex := resources.Get - "indices/contentIndex.json" | resources.Fingerprint "md5" | resources.Minify - }} + {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint "md5" | + resources.Minify | }} {{$contentIndex := resources.Get "indices/contentIndex.json" | + resources.Fingerprint "md5" | resources.Minify }} - {{if $.Site.Data.config.enableSPA}} - {{ $router := resources.Get "js/router.js" | resources.Fingerprint "md5" | - resources.Minify }} + {{if $.Site.Data.config.enableSPA}} {{ $router := resources.Get "js/router.js" | + resources.Fingerprint "md5" | resources.Minify }} {{else}} {{end}} From 006b74ec6feed2d01099754c888bac4a9474a6b1 Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Fri, 27 May 2022 18:45:42 -0700 Subject: [PATCH 051/122] Fix formatting --- layouts/partials/head.html | 40 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 2da259d46..25120d517 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -5,31 +5,44 @@ name="description" content="{{if .IsHome}}{{$.Site.Data.config.description}}{{else}}{{.Summary}}{{end}}" /> - {{ if .Title }}{{ .Title }}{{ else }}{{ $.Site.Data.config.page_title }}{{ end }} + + {{ if .Title }}{{ .Title }}{{ else }}{{ $.Site.Data.config.page_title }}{{ + end }} + - + - {{$sass := resources.Match "styles/[!_]*.scss" }} {{$css := slice }} {{range $sass}} {{$scss := . - | resources.ToCSS (dict "outputStyle" "compressed") }} {{$css = $css | append $scss}} {{end}} - {{$finalCss := $css | resources.Concat "styles.css" | resources.Fingerprint "md5" | - resources.Minify }} + {{$sass := resources.Match "styles/[!_]*.scss" }} + {{$css := slice }} + {{range $sass}} + {{$scss := . | resources.ToCSS (dict "outputStyle" "compressed") }} + {{$css = $css | append $scss}} + {{end}} + {{$finalCss := $css | resources.Concat "styles.css" | resources.Fingerprint "md5" | resources.Minify }} {{ $darkMode := resources.Get "js/darkmode.js" | resources.Fingerprint "md5" | resources.Minify }} - {{partial "katex.html" .}} {{ $popover := resources.Get "js/popover.js" | resources.Fingerprint - "md5" | resources.Minify }} + {{partial "katex.html" .}} + + {{ $popover := resources.Get "js/popover.js" | resources.Fingerprint "md5" | + resources.Minify }} - {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint "md5" | - resources.Minify | }} {{$contentIndex := resources.Get "indices/contentIndex.json" | - resources.Fingerprint "md5" | resources.Minify }} + {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint + "md5" | resources.Minify | }} {{$contentIndex := resources.Get + "indices/contentIndex.json" | resources.Fingerprint "md5" | resources.Minify + }} - {{if $.Site.Data.config.enableSPA}} {{ $router := resources.Get "js/router.js" | - resources.Fingerprint "md5" | resources.Minify }} + {{if $.Site.Data.config.enableSPA}} + {{ $router := resources.Get "js/router.js" | resources.Fingerprint "md5" | + resources.Minify }} {{else}} {{end}} From 5a1fbc937470b4f43b318dd0fa9af01b4a47b188 Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Wed, 1 Jun 2022 13:49:27 +0100 Subject: [PATCH 054/122] Improve graph display, options and ability to have a global graph on the home page, local graphs on subpage. --- assets/js/graph.js | 43 +++++++++++++++++++++++------- data/graphConfig.yaml | 33 +++++++++++++++++++++-- layouts/index.html | 2 +- layouts/partials/footerIndex.html | 28 ++++++++++++++++++++ layouts/partials/head.html | 44 +++++++++++++++++++++++++------ 5 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 layouts/partials/footerIndex.html diff --git a/assets/js/graph.js b/assets/js/graph.js index c7634cf3e..48248ecac 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -1,4 +1,16 @@ -async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, enableZoom) { +async function drawGraph( + baseUrl, + pathColors, + depth, + enableDrag, + enableLegend, + enableZoom, + isHome, + opacityScale, + scale, + repelForce, + fontSize +) { const container = document.getElementById("graph-container") const { index, links, content } = await fetchData @@ -82,12 +94,12 @@ async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, e .on("end", enableDrag ? dragended : noop) } - const height = Math.max(container.offsetHeight, 250) + const height = Math.max(container.offsetHeight, isHome ? 500 : 250) const width = container.offsetWidth const simulation = d3 .forceSimulation(data.nodes) - .force("charge", d3.forceManyBody().strength(-30)) + .force("charge", d3.forceManyBody().strength(-100 * repelForce)) .force( "link", d3 @@ -102,7 +114,7 @@ async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, e .append("svg") .attr("width", width) .attr("height", height) - .attr("viewBox", [-width / 2, -height / 2, width, height]) + .attr('viewBox', [-width / 2 * 1 / scale, -height / 2 * 1 / scale, width * 1 / scale, height * 1 / scale]) if (enableLegend) { const legend = [{ Current: "var(--g-node-active)" }, { Note: "var(--g-node)" }, ...pathColors] @@ -168,7 +180,7 @@ async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, e ]) const neighbourNodes = d3.selectAll(".node").filter((d) => neighbours.includes(d.id)) const currentId = d.id - window.Million.prefetch(new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, "-")}/`)) + // window.Million.prefetch(new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, "-")}/`)) const linkNodes = d3 .selectAll(".link") .filter((d) => d.source.id === currentId || d.target.id === currentId) @@ -179,13 +191,18 @@ async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, e // highlight links linkNodes.transition().duration(200).attr("stroke", "var(--g-link-active)") + const bigFont = fontSize+0.5 + // show text for self d3.select(this.parentNode) .raise() .select("text") .transition() .duration(200) - .style("opacity", 1) + .attr('opacityOld', d3.select(this.parentNode).select('text').style("opacity")) + .style('opacity', 1) + .style('font-size', bigFont+'em') + .attr('dy', d => nodeRadius(d) + 20 + 'px') // radius is in px }) .on("mouseleave", function (_, d) { d3.selectAll(".node").transition().duration(200).attr("fill", color) @@ -197,7 +214,13 @@ async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, e linkNodes.transition().duration(200).attr("stroke", "var(--g-link)") - d3.select(this.parentNode).select("text").transition().duration(200).style("opacity", 0) + d3.select(this.parentNode) + .select("text") + .transition() + .duration(200) + .style('opacity', d3.select(this.parentNode).select('text').attr("opacityOld")) + .style('font-size', fontSize+'em') + .attr('dy', d => nodeRadius(d) + 8 + 'px') // radius is in px }) .call(drag(simulation)) @@ -208,9 +231,9 @@ async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, e .attr("dy", (d) => nodeRadius(d) + 8 + "px") .attr("text-anchor", "middle") .text((d) => content[d.id]?.title || d.id.replace("-", " ")) - .style("opacity", 0) + .style('opacity', (opacityScale - 1) / 3.75) .style("pointer-events", "none") - .style("font-size", "0.4em") + .style('font-size', fontSize+'em') .raise() .call(drag(simulation)) @@ -228,7 +251,7 @@ async function drawGraph(baseUrl, pathColors, depth, enableDrag, enableLegend, e .on("zoom", ({ transform }) => { link.attr("transform", transform) node.attr("transform", transform) - const scale = transform.k + const scale = transform.k * opacityScale; const scaledOpacity = Math.max((scale - 1) / 3.75, 0) labels.attr("transform", transform).style("opacity", scaledOpacity) }), diff --git a/data/graphConfig.yaml b/data/graphConfig.yaml index 3f8d3fb6b..7f08130d8 100644 --- a/data/graphConfig.yaml +++ b/data/graphConfig.yaml @@ -1,6 +1,35 @@ +# if true, a Global Graph will be shown on home page with full width, no backlink. +# A different set of Local Graphs will be shown on sub pages. +# if false, Local Graph will be default on every page as usual +enableGlobalGraph: true + +### Local Graph ### + enableLegend: false enableDrag: true enableZoom: true -depth: -1 # set to -1 to show full graph +depth: 1 # set to -1 to show full graph +scale: 1 +repelForce: 2 +centerForce: 1 +linkDistance: 1 +fontSize: 0.6 +opacityScale: 3 + +### Global Graph ### + +enableLegendGG: false +enableDragGG: true +enableZoomGG: true +depthGG: -1 # set to -1 to show full graph +scaleGG: 1.2 +repelForceGG: 1 +centerForceGG: 1 +linkDistanceGG: 1 +fontSizeGG: 0.5 +opacityScaleGG: 3 + +### Graphs ### + paths: - - /moc: "#4388cc" \ No newline at end of file + - /moc: "#4388cc" diff --git a/layouts/index.html b/layouts/index.html index 8d1ffbd4f..505361420 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -19,7 +19,7 @@ {{partial "recent.html" . }} {{end}} - {{partial "footer.html" .}} + {{partial "footerIndex.html" .}} diff --git a/layouts/partials/footerIndex.html b/layouts/partials/footerIndex.html new file mode 100644 index 000000000..36c8a8ac1 --- /dev/null +++ b/layouts/partials/footerIndex.html @@ -0,0 +1,28 @@ + + +
    + +{{if $.Site.Data.config.enableFooter}} + {{if $.Site.Data.graphConfig.enableGlobalGraph}} +
    + +
    + {{partial "graph.html" .}} +
    + +
    + {{else}} +
    +
    + +
    + {{partial "graph.html" .}} +
    + +
    + {{end}} +{{end}} + +{{partial "contact.html" .}} diff --git a/layouts/partials/head.html b/layouts/partials/head.html index f10ce1453..01b8fe8ab 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -62,6 +62,12 @@ })) const draw = () => { + + const siteBaseURL = new URL({{$.Site.BaseURL}}); + const pathBase = siteBaseURL.pathname; + const pathWindow = window.location.pathname; + const isHome = pathBase == pathWindow ? true : false; + // 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. {{if $.Site.Data.config.enableFooter}} const container = document.getElementById("graph-container") @@ -70,14 +76,36 @@ // clear the graph in case there is anything within it container.textContent = "" - 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 (isHome && {{$.Site.Data.graphConfig.enableGlobalGraph}}) { + drawGraph( + {{strings.TrimRight "/" .Site.BaseURL}}, + {{$.Site.Data.graphConfig.paths}}, + {{$.Site.Data.graphConfig.depthGG}}, + {{$.Site.Data.graphConfig.enableDragGG}}, + {{$.Site.Data.graphConfig.enableLegendGG}}, + {{$.Site.Data.graphConfig.enableZoomGG}}, + true, + {{$.Site.Data.graphConfig.opacityScaleGG}}, + {{$.Site.Data.graphConfig.scaleGG}}, + {{$.Site.Data.graphConfig.repelForceGG}}, + {{$.Site.Data.graphConfig.fontSizeGG}} + ); + } else { + 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}}, + false, + {{$.Site.Data.graphConfig.opacityScale}}, + {{$.Site.Data.graphConfig.scale}}, + {{$.Site.Data.graphConfig.repelForce}}, + {{$.Site.Data.graphConfig.fontSize}} + ); + } + {{end}} {{if $.Site.Data.config.enableLinkPreview}} initPopover( From 1e237ef677f3b958597460175269eed4b0638112 Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Wed, 1 Jun 2022 20:15:44 +0100 Subject: [PATCH 055/122] change baseURL --- config.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.toml b/config.toml index 5efa9f346..6a7838122 100644 --- a/config.toml +++ b/config.toml @@ -1,4 +1,4 @@ -baseURL = "https://quartz.jzhao.xyz/" +baseURL = "https://dhammacharts.org/quartz/" languageCode = "en-us" googleAnalytics = "G-XYFD95KB4J" pygmentsUseClasses = true @@ -30,4 +30,4 @@ enableGitInfo = true tabWidth = 4 [frontmatter] lastmod = ["lastmod", ":git", "date", "publishDate"] - publishDate = ["publishDate", "date"] \ No newline at end of file + publishDate = ["publishDate", "date"] From 19606ba63d15edd1e4a98bf1ce5cd510a24880e0 Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:19:03 +0100 Subject: [PATCH 056/122] add www. --- config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.toml b/config.toml index 6a7838122..65ffb1f21 100644 --- a/config.toml +++ b/config.toml @@ -1,4 +1,4 @@ -baseURL = "https://dhammacharts.org/quartz/" +baseURL = "https://www.dhammacharts.org/quartz/" languageCode = "en-us" googleAnalytics = "G-XYFD95KB4J" pygmentsUseClasses = true From e809896338b51e65ca862809e79884469476f2de Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:22:31 +0100 Subject: [PATCH 057/122] increase scale --- data/graphConfig.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/graphConfig.yaml b/data/graphConfig.yaml index 7f08130d8..f8b9941dc 100644 --- a/data/graphConfig.yaml +++ b/data/graphConfig.yaml @@ -9,7 +9,7 @@ enableLegend: false enableDrag: true enableZoom: true depth: 1 # set to -1 to show full graph -scale: 1 +scale: 1.2 repelForce: 2 centerForce: 1 linkDistance: 1 @@ -22,7 +22,7 @@ enableLegendGG: false enableDragGG: true enableZoomGG: true depthGG: -1 # set to -1 to show full graph -scaleGG: 1.2 +scaleGG: 1.4 repelForceGG: 1 centerForceGG: 1 linkDistanceGG: 1 From ac0dd50c048d68884b0ada42e3ab0476fb29ef65 Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:30:40 +0100 Subject: [PATCH 058/122] uncomment window.Million --- assets/js/graph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index 48248ecac..87d8d586e 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -180,7 +180,7 @@ async function drawGraph( ]) const neighbourNodes = d3.selectAll(".node").filter((d) => neighbours.includes(d.id)) const currentId = d.id - // window.Million.prefetch(new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, "-")}/`)) + window.Million.prefetch(new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, "-")}/`)) const linkNodes = d3 .selectAll(".link") .filter((d) => d.source.id === currentId || d.target.id === currentId) From c0800a874980ab0f24fc2e350d70792d9c7f2956 Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Thu, 2 Jun 2022 07:45:44 +0100 Subject: [PATCH 059/122] change baseURL back to original --- config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.toml b/config.toml index 65ffb1f21..803ef1ecb 100644 --- a/config.toml +++ b/config.toml @@ -1,4 +1,4 @@ -baseURL = "https://www.dhammacharts.org/quartz/" +baseURL = "https://quartz.jzhao.xyz/" languageCode = "en-us" googleAnalytics = "G-XYFD95KB4J" pygmentsUseClasses = true From d261655d96f9ed084a176ed113b0d11f1351c6de Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Thu, 2 Jun 2022 07:49:09 +0100 Subject: [PATCH 060/122] remove unnecessary ternary --- layouts/partials/head.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 01b8fe8ab..b56c29136 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -66,7 +66,7 @@ const siteBaseURL = new URL({{$.Site.BaseURL}}); const pathBase = siteBaseURL.pathname; const pathWindow = window.location.pathname; - const isHome = pathBase == pathWindow ? true : false; + const isHome = pathBase == pathWindow; // 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. {{if $.Site.Data.config.enableFooter}} From c88f31c3645bb0002171bf21850c7ca6d217c73f Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Thu, 2 Jun 2022 08:16:02 +0100 Subject: [PATCH 061/122] change to object destructuring for drawGraph() arguments --- assets/js/graph.js | 11 +++++----- data/graphConfig.yaml | 44 ++++++++++++++++++++------------------ layouts/partials/head.html | 22 ++++--------------- 3 files changed, 32 insertions(+), 45 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index 87d8d586e..9199bef89 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -1,16 +1,15 @@ -async function drawGraph( - baseUrl, - pathColors, +async function drawGraph(baseUrl,isHome,pathColors,graphConfig) { + + let { depth, enableDrag, enableLegend, enableZoom, - isHome, opacityScale, scale, repelForce, - fontSize -) { + fontSize} = graphConfig; + const container = document.getElementById("graph-container") const { index, links, content } = await fetchData diff --git a/data/graphConfig.yaml b/data/graphConfig.yaml index f8b9941dc..06ce2b08f 100644 --- a/data/graphConfig.yaml +++ b/data/graphConfig.yaml @@ -5,31 +5,33 @@ enableGlobalGraph: true ### Local Graph ### -enableLegend: false -enableDrag: true -enableZoom: true -depth: 1 # set to -1 to show full graph -scale: 1.2 -repelForce: 2 -centerForce: 1 -linkDistance: 1 -fontSize: 0.6 -opacityScale: 3 +localGraph: + enableLegend: false + enableDrag: true + enableZoom: true + depth: 1 # set to -1 to show full graph + scale: 1.2 + repelForce: 2 + centerForce: 1 + linkDistance: 1 + fontSize: 0.6 + opacityScale: 3 ### Global Graph ### -enableLegendGG: false -enableDragGG: true -enableZoomGG: true -depthGG: -1 # set to -1 to show full graph -scaleGG: 1.4 -repelForceGG: 1 -centerForceGG: 1 -linkDistanceGG: 1 -fontSizeGG: 0.5 -opacityScaleGG: 3 +globalGraph: + enableLegend: false + enableDrag: true + enableZoom: true + depth: -1 # set to -1 to show full graph + scale: 1.4 + repelForce: 1 + centerForce: 1 + linkDistance: 1 + fontSize: 0.5 + opacityScale: 3 -### Graphs ### +### For all graphs ### paths: - /moc: "#4388cc" diff --git a/layouts/partials/head.html b/layouts/partials/head.html index b56c29136..ba02260e4 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -79,30 +79,16 @@ if (isHome && {{$.Site.Data.graphConfig.enableGlobalGraph}}) { drawGraph( {{strings.TrimRight "/" .Site.BaseURL}}, - {{$.Site.Data.graphConfig.paths}}, - {{$.Site.Data.graphConfig.depthGG}}, - {{$.Site.Data.graphConfig.enableDragGG}}, - {{$.Site.Data.graphConfig.enableLegendGG}}, - {{$.Site.Data.graphConfig.enableZoomGG}}, true, - {{$.Site.Data.graphConfig.opacityScaleGG}}, - {{$.Site.Data.graphConfig.scaleGG}}, - {{$.Site.Data.graphConfig.repelForceGG}}, - {{$.Site.Data.graphConfig.fontSizeGG}} + {{$.Site.Data.graphConfig.paths}}, + {{$.Site.Data.graphConfig.globalGraph}} ); } else { 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}}, false, - {{$.Site.Data.graphConfig.opacityScale}}, - {{$.Site.Data.graphConfig.scale}}, - {{$.Site.Data.graphConfig.repelForce}}, - {{$.Site.Data.graphConfig.fontSize}} + {{$.Site.Data.graphConfig.paths}}, + {{$.Site.Data.graphConfig.localGraph}} ); } From a275123be2b1d528dbde23beb9880933c4e22c3e Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Thu, 2 Jun 2022 08:35:28 +0100 Subject: [PATCH 062/122] better font behaviour --- assets/js/graph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index 9199bef89..f79cb3fa4 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -190,7 +190,7 @@ async function drawGraph(baseUrl,isHome,pathColors,graphConfig) { // highlight links linkNodes.transition().duration(200).attr("stroke", "var(--g-link-active)") - const bigFont = fontSize+0.5 + const bigFont = fontSize*1.5 // show text for self d3.select(this.parentNode) From ab809249c8f57c1980de2fa850eef66301619307 Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Mon, 6 Jun 2022 16:42:53 +0100 Subject: [PATCH 063/122] Update layouts/partials/head.html Co-authored-by: Jacky Zhao --- layouts/partials/head.html | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 6eb8eaf36..b3ad28d8c 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -72,21 +72,13 @@ // clear the graph in case there is anything within it container.textContent = "" - if (isHome && {{$.Site.Data.graphConfig.enableGlobalGraph}}) { - drawGraph( + const drawGlobal = isHome && {{$.Site.Data.graphConfig.enableGlobalGraph}}; + drawGraph( {{strings.TrimRight "/" .Site.BaseURL}}, - true, + drawGlobal, {{$.Site.Data.graphConfig.paths}}, - {{$.Site.Data.graphConfig.globalGraph}} + drawGlobal ? {{$.Site.Data.graphConfig.globalGraph}} : {{$.Site.Data.graphConfig.localGraph}} ); - } else { - drawGraph( - {{strings.TrimRight "/" .Site.BaseURL}}, - false, - {{$.Site.Data.graphConfig.paths}}, - {{$.Site.Data.graphConfig.localGraph}} - ); - } {{end}} From 69c74ca6b5854cbb3e7dd895dca0539f51f49720 Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Mon, 6 Jun 2022 16:48:16 +0100 Subject: [PATCH 064/122] minor adjustment --- assets/js/graph.js | 2 +- layouts/partials/footerIndex.html | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index f79cb3fa4..174d4946d 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -1,4 +1,4 @@ -async function drawGraph(baseUrl,isHome,pathColors,graphConfig) { +async function drawGraph(baseUrl, isHome, pathColors, graphConfig) { let { depth, diff --git a/layouts/partials/footerIndex.html b/layouts/partials/footerIndex.html index 36c8a8ac1..5f190446a 100644 --- a/layouts/partials/footerIndex.html +++ b/layouts/partials/footerIndex.html @@ -1,7 +1,3 @@ - - -
    - {{if $.Site.Data.config.enableFooter}} {{if $.Site.Data.graphConfig.enableGlobalGraph}}
    From 52a185f73b18d8e5a564c2144401de750b0e025a Mon Sep 17 00:00:00 2001 From: DhammaCharts <100090806+DhammaCharts@users.noreply.github.com> Date: Mon, 6 Jun 2022 16:49:01 +0100 Subject: [PATCH 065/122] change enableGlobalGraph to false --- data/graphConfig.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/graphConfig.yaml b/data/graphConfig.yaml index 06ce2b08f..a6f916acb 100644 --- a/data/graphConfig.yaml +++ b/data/graphConfig.yaml @@ -1,7 +1,7 @@ # if true, a Global Graph will be shown on home page with full width, no backlink. # A different set of Local Graphs will be shown on sub pages. # if false, Local Graph will be default on every page as usual -enableGlobalGraph: true +enableGlobalGraph: false ### Local Graph ### From 473ea2c66f9122cec2647c281ca47cc073ca5fd0 Mon Sep 17 00:00:00 2001 From: Geoffrey Garrett Date: Mon, 27 Jun 2022 22:04:32 +0200 Subject: [PATCH 066/122] feat(layouts/partials/head.html): Adds general favicon support with dict and string input format --- layouts/partials/head.html | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index b3ad28d8c..7b8bb4eb5 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -10,7 +10,17 @@ end }} - + + + {{ $favicon := $.Site.Data.config.favicon | default (slice (dict "rel" "shortcut icon" "type" "image/png" "href" "icon.png")) }} + {{ $type := (printf "%T" $favicon) }} + {{ if eq $type "string" }} + {{ $favicon | safeHTML }} + {{ else }} + {{ range $favicon }} + + {{- end }} + {{ end }} Date: Mon, 27 Jun 2022 22:05:35 +0200 Subject: [PATCH 067/122] docs(content/notes/config.md): Adds documentation for the new favicon support --- content/notes/config.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/content/notes/config.md b/content/notes/config.md index d04b1528d..691e18740 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -23,6 +23,40 @@ links: # Links to show in footer link: https://github.com/jackyzha0 ``` +### HTML Favicons + +If you would like to customize the favicons of your website, you can add them to the `data/config.yaml` file. The default without any set `favicon` key is: + +```html + +``` + +The default can be overridden by defining a value to the `favicon` key in your `data/config.yaml` file. Here is a `List[Dictionary]` example format, which is equivalent to the default: + +```yaml +favicon: + - { rel: "shortcut icon", href: "icon.png", type: "image/png" } +``` + +In this format, the following keys are available: +- `rel`: The `rel` attribute of the `` tag. +- `type`: The `type` attribute of the `` tag. +- `href` (optional): The `href` attribute of the `` tag. +- `sizes` (optional): The `sizes` attribute of the `` tag. + +If you plan to add multiple favicons generated by a website, it may be easier to define it as HTML: + +```yaml +favicon: | + +``` + +Some websites that **generate favicons** for you (ordered alphabetically) include: +- [`favicon.io`](https://favicon.io/) +- [`realfavicongenerator.net`](https://realfavicongenerator.net/) +- [`www.favicon.cc`](https://www.favicon.cc/) + + ### Graph View To customize the Interactive Graph view, you can poke around `data/graphConfig.yaml`. From 997937af5a6dc317da56ae294dce927ec5930a4b Mon Sep 17 00:00:00 2001 From: Geoffrey Garrett Date: Tue, 28 Jun 2022 00:45:48 +0200 Subject: [PATCH 068/122] docs(config.md): Added short explainer on favicons --- content/notes/config.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/content/notes/config.md b/content/notes/config.md index 691e18740..8c758edd9 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -25,7 +25,13 @@ links: # Links to show in footer ### HTML Favicons -If you would like to customize the favicons of your website, you can add them to the `data/config.yaml` file. The default without any set `favicon` key is: +A Favicon is most commonly seen preceding the URL in a browser. Some +other examples include (but are not limited to) bookmarks, search history, and +app icons (i.e. "save page to homescreen" on mobile devices). [File format support](https://en.wikipedia.org/wiki/Favicon#File_format_support) +and the [use of favicons](https://en.wikipedia.org/wiki/Favicon#Use_of_favicon) differ +across the combination of platforms and browsers. + +If you would like to customize the favicons of your website, you can add them to the `data/config.yaml` file. The **default** without any set `favicon` key is: ```html From 7070a1992a6c9462d50afcc7139f8f97e1dce2b8 Mon Sep 17 00:00:00 2001 From: Geoffrey Garrett Date: Tue, 28 Jun 2022 01:15:33 +0200 Subject: [PATCH 069/122] docs(config.md): Fixed multi-favicon examples and general favicon explanation throughout --- content/notes/config.md | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/content/notes/config.md b/content/notes/config.md index 8c758edd9..c9cbd0a4b 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -25,23 +25,29 @@ links: # Links to show in footer ### HTML Favicons -A Favicon is most commonly seen preceding the URL in a browser. Some -other examples include (but are not limited to) bookmarks, search history, and -app icons (i.e. "save page to homescreen" on mobile devices). [File format support](https://en.wikipedia.org/wiki/Favicon#File_format_support) -and the [use of favicons](https://en.wikipedia.org/wiki/Favicon#Use_of_favicon) differ -across the combination of platforms and browsers. +A Favicon is most commonly seen as the **image preceding the URL in a browser**. +Some other examples include (but are not limited to) bookmarks, search history, +and app icons (i.e. "save page to home screen" on mobile devices). +[File format support](https://en.wikipedia.org/wiki/Favicon#File_format_support) +and the [use of favicons](https://en.wikipedia.org/wiki/Favicon#Use_of_favicon) +differ across the combination of platforms and browsers. -If you would like to customize the favicons of your website, you can add them to the `data/config.yaml` file. The **default** without any set `favicon` key is: +If you would like to customize the favicons of your quartz-based website, you +can add them to the `data/config.yaml` file. The **default** without any set +`favicon` key is: ```html ``` -The default can be overridden by defining a value to the `favicon` key in your `data/config.yaml` file. Here is a `List[Dictionary]` example format, which is equivalent to the default: +The default can be overridden by defining a value to the `favicon` key in your +`data/config.yaml` file. Here is a `List[Dictionary]` example format, which is +equivalent to the default: ```yaml favicon: - { rel: "shortcut icon", href: "icon.png", type: "image/png" } +# - { ... } # Repeat for each additional favicon you want to add ``` In this format, the following keys are available: @@ -50,18 +56,34 @@ In this format, the following keys are available: - `href` (optional): The `href` attribute of the `` tag. - `sizes` (optional): The `sizes` attribute of the `` tag. -If you plan to add multiple favicons generated by a website, it may be easier to define it as HTML: +If you plan to add multiple favicons generated by a website (see list below), it +may be easier to define it as HTML. Here is an example which appends the +**Apple touch icon** to quartz's default favicon: ```yaml favicon: | + ``` +This second favicon will now be used as a web page icon when someone adds your +webpage to the home screen of their Apple device. If you are interested in more +information about the current, and past, standards of favicons, you can read +[this article](https://www.emergeinteractive.com/insights/detail/the-essentials-of-favicons/). + Some websites that **generate favicons** for you (ordered alphabetically) include: - [`favicon.io`](https://favicon.io/) - [`realfavicongenerator.net`](https://realfavicongenerator.net/) - [`www.favicon.cc`](https://www.favicon.cc/) +These sites will take a base image and generate a set of favicons for you, +one of which will be, for example, the `apple-touch-icon` favicon. These sites +will often **also provide the HTML** for the favicon, which can be simply +added to the `data/config.yaml` using the HTML format of the `favicon` +argument. + +**Note** that all generated favicon paths, defined by the `href` +attribute, are relative to the `static/` directory. ### Graph View To customize the Interactive Graph view, you can poke around `data/graphConfig.yaml`. From b732293f65999e9a1d3a40a5ddeccf53a385b1f3 Mon Sep 17 00:00:00 2001 From: Geoffrey Garrett Date: Tue, 28 Jun 2022 01:21:22 +0200 Subject: [PATCH 070/122] fix(head.html): Adds robustness to `config.yaml` favicon definitions Initially assumed that `href` definitions should have `/...` as their pattern, and `baseURL` would always end with `/`, however the omission of `/` as the prefix of the former and suffix of the latter simultaneously, would result in broken favicon paths. Final comment: `..///...` is not breaking, which is worst case scenario with this fix. --- layouts/partials/head.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 7b8bb4eb5..d33a0c7b2 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -18,7 +18,7 @@ {{ $favicon | safeHTML }} {{ else }} {{ range $favicon }} - + {{- end }} {{ end }} From 67a7ba37e899ca0555fa37e159af6d599cf468ee Mon Sep 17 00:00:00 2001 From: Aiden Bai Date: Tue, 28 Jun 2022 21:43:28 -0700 Subject: [PATCH 071/122] Bump million to 1.11.3 --- assets/js/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/router.js b/assets/js/router.js index 3bdc81023..b2b6d2119 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -3,7 +3,7 @@ import { navigate, prefetch, router, -} from "https://unpkg.com/million@1.9.8-0/dist/router.mjs" +} from "https://unpkg.com/million@1.11.3/dist/router.mjs" export const attachSPARouting = (init, rerender) => { // Attach SPA functions to the global Million namespace From f2078ee621b7137c49b176156ff70ddb5359d5a8 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 29 Jun 2022 16:12:33 -0700 Subject: [PATCH 072/122] fix: prefix images with base url for non-root quartz --- layouts/_default/_markup/render-image.html | 2 +- layouts/partials/head.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/layouts/_default/_markup/render-image.html b/layouts/_default/_markup/render-image.html index ff4e8b39c..8dda6a8c0 100644 --- a/layouts/_default/_markup/render-image.html +++ b/layouts/_default/_markup/render-image.html @@ -4,5 +4,5 @@ {{ .Text }} {{- else -}} {{$fixedUrl := (cond (hasPrefix $src "/") $src (print "/" $src)) | urlize}} -{{ .Text }} +{{ .Text }} {{- end -}} diff --git a/layouts/partials/head.html b/layouts/partials/head.html index d33a0c7b2..a364cca2e 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -70,7 +70,7 @@ const render = () => { // 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, adds event listeners, etc. If you are only dealing with basic DOM replacement, use the init function - const siteBaseURL = new URL({{$.Site.BaseURL}}); + const siteBaseURL = new URL(BASE_URL); const pathBase = siteBaseURL.pathname; const pathWindow = window.location.pathname; const isHome = pathBase == pathWindow; From 200c60514207d7970968e31740797fad76f56ee7 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 29 Jun 2022 16:16:06 -0700 Subject: [PATCH 073/122] feat: enable raw html by default (fixes #143) --- config.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.toml b/config.toml index 803ef1ecb..94c2f9b40 100644 --- a/config.toml +++ b/config.toml @@ -31,3 +31,5 @@ enableGitInfo = true [frontmatter] lastmod = ["lastmod", ":git", "date", "publishDate"] publishDate = ["publishDate", "date"] + [markup.goldmark.renderer] + unsafe = true From 8a100edeb81382dc838f600ee1b8dbd3e7560e37 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 29 Jun 2022 16:57:36 -0700 Subject: [PATCH 074/122] docs: polish and update --- content/_index.md | 11 ++- content/notes/config.md | 125 ++++++++++++++++++++++--------- content/notes/editing.md | 29 ++++--- content/notes/hosting.md | 12 ++- content/notes/obsidian.md | 3 + content/notes/preview changes.md | 11 +-- content/notes/setup.md | 30 +------- content/notes/updating.md | 34 +++++++++ 8 files changed, 159 insertions(+), 96 deletions(-) create mode 100644 content/notes/updating.md diff --git a/content/_index.md b/content/_index.md index bd742c4de..7d6d3f98a 100644 --- a/content/_index.md +++ b/content/_index.md @@ -11,17 +11,16 @@ Host your second brain and [digital garden](https://jzhao.xyz/posts/networked-th 5. Support for both Markdown Links and Wikilinks ## Get Started -> 📚 [Setup your own digital garden using Quartz](notes/setup.md) +> 📚 Step 1: [Setup your own digital garden using Quartz](notes/setup.md) Not convinced yet? Look at some [community digital gardens](notes/showcase.md) built with Quartz, or read about [why I made Quartz](notes/philosophy.md) to begin with. -## Content Lists -If you prefer browsing the contents of this site through a list instead of a graph, you can find content lists here too: +Returning user? Figure out how to [[notes/updating|update]] your existing Quartz garden. -- [All Notes](/notes) -- [Setup-related Notes](/tags/setup) +### Content Lists +If you prefer browsing the contents of this site through a list instead of a graph, you see a list of all [setup-related notes](/tags/setup). -## Troubleshooting +### Troubleshooting - 🚧 [Troubleshooting and FAQ](notes/troubleshooting.md) - 🐛 [Submit an Issue](https://github.com/jackyzha0/quartz/issues) - 👀 [Discord Community](https://discord.gg/cRFFHYye7t) diff --git a/content/notes/config.md b/content/notes/config.md index c9cbd0a4b..6e18073cc 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -2,6 +2,7 @@ title: "Configuration" tags: - setup +weight: 5 --- ## Configuration @@ -10,13 +11,49 @@ Quartz is designed to be extremely configurable. You can find the bulk of the co The majority of configuration can be be found under `data/config.yaml`. An annotated example configuration is shown below. ```yaml -name: Your name here! # Shows in the footer -enableToc: true # Whether to show a Table of Contents -enableLinkPreview: true # whether to render card previews for links -description: Page description to show to search engines -page_title: Quartz Example Page # Default Page Title +# The name to display in the footer +name: Jacky Zhao -links: # Links to show in footer +# whether to globally show the table of contents on each page +# this can be turned off on a per-page basis by adding this to the +# front-matter of that note +enableToc: true + +# whether to by-default open or close the table of contents on each page +openToc: false + +# whether to display on-hover link preview cards +enableLinkPreview: true + +# whether to try to process Latex +enableLatex: true + +# whether to enable single-page-app style rendering +# this prevents flahses of unstyled content and overall improves +# smoothness of quartz. More info in issue #109 on GitHub +enableSPA: true + +# whether to render a footer +enableFooter: true + +# whether backlinks of pages should show the context in which +# they were mentioned +enableContextualBacklinks: true + +# whether to show a section of recent notes on the home page +enableRecentNotes: false + +# page description used for SEO +description: + Host your second brain and digital garden for free. Quartz features extremely fast full-text search, + Wikilink support, backlinks, local graph, tags, and link previews. + +# title of the home page (also for SEO) +page_title: + "🪴 Quartz 3.2" + +# links to show in the footer +links: - link_name: Twitter link: https://twitter.com/_jzhao - link_name: Github @@ -24,14 +61,6 @@ links: # Links to show in footer ``` ### HTML Favicons - -A Favicon is most commonly seen as the **image preceding the URL in a browser**. -Some other examples include (but are not limited to) bookmarks, search history, -and app icons (i.e. "save page to home screen" on mobile devices). -[File format support](https://en.wikipedia.org/wiki/Favicon#File_format_support) -and the [use of favicons](https://en.wikipedia.org/wiki/Favicon#Use_of_favicon) -differ across the combination of platforms and browsers. - If you would like to customize the favicons of your quartz-based website, you can add them to the `data/config.yaml` file. The **default** without any set `favicon` key is: @@ -50,11 +79,7 @@ favicon: # - { ... } # Repeat for each additional favicon you want to add ``` -In this format, the following keys are available: -- `rel`: The `rel` attribute of the `` tag. -- `type`: The `type` attribute of the `` tag. -- `href` (optional): The `href` attribute of the `` tag. -- `sizes` (optional): The `sizes` attribute of the `` tag. +In this format, the keys are identical to their HTML representations. If you plan to add multiple favicons generated by a website (see list below), it may be easier to define it as HTML. Here is an example which appends the @@ -71,17 +96,6 @@ webpage to the home screen of their Apple device. If you are interested in more information about the current, and past, standards of favicons, you can read [this article](https://www.emergeinteractive.com/insights/detail/the-essentials-of-favicons/). -Some websites that **generate favicons** for you (ordered alphabetically) include: -- [`favicon.io`](https://favicon.io/) -- [`realfavicongenerator.net`](https://realfavicongenerator.net/) -- [`www.favicon.cc`](https://www.favicon.cc/) - -These sites will take a base image and generate a set of favicons for you, -one of which will be, for example, the `apple-touch-icon` favicon. These sites -will often **also provide the HTML** for the favicon, which can be simply -added to the `data/config.yaml` using the HTML format of the `favicon` -argument. - **Note** that all generated favicon paths, defined by the `href` attribute, are relative to the `static/` directory. @@ -89,11 +103,50 @@ attribute, are relative to the `static/` directory. To customize the Interactive Graph view, you can poke around `data/graphConfig.yaml`. ```yaml -enableLegend: false # automatically generate a legend -enableDrag: true # allow dragging nodes in the graph -enableZoom: true # allow zooming and panning the graph -depth: -1 # how many neighbours of the current node to show (-1 is all nodes) -paths: # colour specific nodes path off of their path +# if true, a Global Graph will be shown on home page with full width, no backlink. +# A different set of Local Graphs will be shown on sub pages. +# if false, Local Graph will be default on every page as usual +enableGlobalGraph: false + +### Local Graph ### +localGraph: + # whether automatically generate a legend + enableLegend: false + + # whether to allow dragging nodes in the graph + enableDrag: true + + # whether to allow zooming and panning the graph + enableZoom: true + + # how many neighbours of the current node to show (-1 is all nodes) + depth: 1 + + # initial zoom factor of the graph + scale: 1.2 + + # how strongly nodes should repel each other + repelForce: 2 + + # how strongly should nodes be attracted to the center of gravity + centerForce: 1 + + # what the default link length should be + linkDistance: 1 + + # how big the node labels should be + fontSize: 0.6 + + # scale at which to start fading the labes on nodes + opacityScale: 3 + +### Global Graph ### +globalGraph: + # same settings as above + +### For all graphs ### +# colour specific nodes path off of their path +paths: - /moc: "#4388cc" ``` @@ -110,7 +163,7 @@ More info about partials on [Hugo's website.](https://gohugo.io/templates/partia Still having problems? Checkout our [FAQ and Troubleshooting guide](notes/troubleshooting.md). -## Multilingual +## Language Support [CJK + Latex Support (测试)](notes/CJK%20+%20Latex%20Support%20(测试).md) comes out of the box with Quartz. Want to support languages that read from right-to-left (like Arabic)? Hugo (and by proxy, Quartz) supports this natively. diff --git a/content/notes/editing.md b/content/notes/editing.md index c8cefa0cc..af7dd7712 100644 --- a/content/notes/editing.md +++ b/content/notes/editing.md @@ -2,29 +2,18 @@ title: "Editing Content in Quartz" tags: - setup +weight: 1 --- ## Editing Quartz runs on top of [Hugo](https://gohugo.io/) so all notes are written in [Markdown](https://www.markdownguide.org/getting-started/). -### Obsidian -I recommend using [Obsidian](http://obsidian.md/) as a way to edit and grow your digital garden. It comes with a really nice editor and graphical interface to preview all of your local files. - -This step is **highly recommended**. - -🔗 [How to setup your Obsidian Vault to work with Quartz](notes/obsidian.md) - -### Ignoring Files -Only want to publish a subset of all of your notes? Don't worry, Quartz makes this a simple two-step process. - -❌ [Excluding pages from being published](notes/ignore%20notes.md) - ### Folder Structure Here's a rough overview of what's what. **All content in your garden can found in the `/content` folder.** To make edits, you can open any of the files and make changes directly and save it. You can organize content into any folder you'd like. -**To edit the main home page, open `/content/_index.md`.* +**To edit the main home page, open `/content/_index.md`.** To create a link between notes in your garden, just create a normal link using Markdown pointing to the document in question. Please note that **all links should be relative to the root `/content` path**. @@ -40,6 +29,8 @@ Example image (source is in content/notes/images/example.png) ![Example Image](/content/notes/images/example.png) ``` +You can also use wikilinks if that is what you are more comfortable with! + ### Front Matter Hugo is picky when it comes to metadata for files. Make sure that your title is double-quoted and that you have a title defined at the top of your file like so. You can also add tags here as well. @@ -48,22 +39,28 @@ Hugo is picky when it comes to metadata for files. Make sure that your title is title: "Example Title" tags: - example-tag -enableToc: false # do not show a table of contents on this page --- Rest of your content here... ``` +### Obsidian +I recommend using [Obsidian](http://obsidian.md/) as a way to edit and grow your digital garden. It comes with a really nice editor and graphical interface to preview all of your local files. + +This step is **highly recommended**. + +> 🔗 Step 3: [How to setup your Obsidian Vault to work with Quartz](notes/obsidian.md) + ## Previewing Changes This step is purely optional and mostly for those who want to see the published version of their digital garden locally before opening it up to the internet. This is *highly recommended* but not required. -👀 [Preview Quartz Changes](notes/preview%20changes.md) +> 👀 Step 4: [Preview Quartz Changes](notes/preview%20changes.md) For those who like to live life more on the edge, viewing the garden through Obsidian gets you pretty close to the real thing. ## Publishing Changes Now that you know the basics of managing your digital garden using Quartz, you can publish it to the internet! -🌍 [Hosting Quartz online!](notes/hosting.md) +> 🌍 Step 5: [Hosting Quartz online!](notes/hosting.md) Having problems? Checkout our [FAQ and Troubleshooting guide](notes/troubleshooting.md). diff --git a/content/notes/hosting.md b/content/notes/hosting.md index bb1d912ed..adda82d44 100644 --- a/content/notes/hosting.md +++ b/content/notes/hosting.md @@ -2,6 +2,7 @@ title: "Deploying Quartz to the Web" tags: - setup +weight: 4 --- ## GitHub Pages @@ -41,7 +42,7 @@ Note: we specifically push to the `hugo` branch here. Our GitHub action automati ### Setting up the Site Now let's get this site up and running. Never hosted a site before? No problem. Have a fancy custom domain you already own or want to subdomain your Quartz? That's easy too. -Here, we take advantage of GitHub's free page hosting to deploy our site. Change `baseURL` in `/config.toml`. +Here, we take advantage of GitHub's free page hosting to deploy our site. Change `baseURL` in `/config.toml`. Make sure that your `baseURL` has a trailing `/`! @@ -51,7 +52,7 @@ Make sure that your `baseURL` has a trailing `/`! baseURL = "https:///" ``` -If you are using this under a subdomain (e.g. `.github.io/quartz`), include the trailing `/`. +If you are using this under a subdomain (e.g. `.github.io/quartz`), include the trailing `/`. **You need to do this especially if you are using GitHub!** ```toml baseURL = "https://.github.io/quartz/" @@ -75,10 +76,15 @@ Please note that the `cname` field should *not* have any path `e.g. end with /qu Have a custom domain? [Learn how to set it up with Quartz ](notes/custom%20Domain.md). +### Ignoring Files +Only want to publish a subset of all of your notes? Don't worry, Quartz makes this a simple two-step process. + +❌ [Excluding pages from being published](notes/ignore%20notes.md) + --- Now that your Quartz is live, let's figure out how to make Quartz really *yours*! -🎨 [Customizing Quartz](notes/config.md) +> Step 6: 🎨 [Customizing Quartz](notes/config.md) Having problems? Checkout our [FAQ and Troubleshooting guide](notes/troubleshooting.md). diff --git a/content/notes/obsidian.md b/content/notes/obsidian.md index 8e5fedd82..66cd78d9e 100644 --- a/content/notes/obsidian.md +++ b/content/notes/obsidian.md @@ -2,6 +2,7 @@ title: "Obsidian Vault Integration" tags: - setup +weight: 2 --- ## Setup @@ -27,3 +28,5 @@ Inserting front matter everytime you want to create a new Note gets annoying rea **If you decide to overwrite the `/content` folder completely, don't remove the `/content/templates` folder!** Head over to Options > Core Plugins and enable the Templates plugin. Then go to Options > Hotkeys and set a hotkey for 'Insert Template' (I recommend `[cmd]+T`). That way, when you create a new note, you can just press the hotkey for a new template and be ready to go! + +> 👀 Step 4: [Preview Quartz Changes](notes/preview%20changes.md) \ No newline at end of file diff --git a/content/notes/preview changes.md b/content/notes/preview changes.md index 7f12f3055..3130c58ed 100644 --- a/content/notes/preview changes.md +++ b/content/notes/preview changes.md @@ -1,5 +1,6 @@ --- title: "Preview Changes" +weight: 3 --- If you'd like to preview what your Quartz site looks like before deploying it to the internet, here's exactly how to do that! @@ -12,12 +13,6 @@ This step will generate the list of backlinks for Hugo to parse. Ensure you have ```shell # Install and link `hugo-obsidian` locally $ go install github.com/jackyzha0/hugo-obsidian@latest - -# Navigate to your local Quartz folder -$ cd - -# Scrape all links in your Quartz folder and generate info for Quartz -$ hugo-obsidian -input=content -output=assets/indices -index -root=. ``` If you are running into an error saying that `command not found: hugo-obsidian`, make sure you set your `GOPATH` correctly! This will allow your terminal to correctly recognize hugo-obsidian as an executable. @@ -32,7 +27,9 @@ Hugo is the static site generator that powers Quartz. [Install Hugo with "extend $ cd # Start local server -$ hugo server +$ make serve # View your site in a browser at http://localhost:1313/ ``` + +> 🌍 Step 5: [Hosting Quartz online!](notes/hosting.md) \ No newline at end of file diff --git a/content/notes/setup.md b/content/notes/setup.md index 495a43b68..fffb0fb25 100644 --- a/content/notes/setup.md +++ b/content/notes/setup.md @@ -2,6 +2,7 @@ title: "Setup" tags: - setup +weight: 0 --- ## Making your own Quartz @@ -26,33 +27,6 @@ $ git clone https://github.com/YOUR-USERNAME/quartz ## Editing Great! Now you have everything you need to start editing and growing your digital garden. If you're ready to start writing content already, check out the recommended flow for editing notes in Quartz. -✏️ [Editing Notes in Quartz](notes/editing.md) +> ✏️ Step 2: [Editing Notes in Quartz](notes/editing.md) Having problems? Checkout our [FAQ and Troubleshooting guide](notes/troubleshooting.md). - -## Updating -Haven't updated Quartz in a while and want all the cool new optimizations? On Unix/Mac systems you can run the following command for a one-line update! This command will show you a log summary of all commits since you last updated, press `q` to acknowledge this. Then, it will show you each change in turn and press `y` to accept the patch or `n` to reject it. Usually you should press `y` for most of these unless it conflicts with existing changes you've made! - -```shell -make update - -# or, if you don't want the interactive parts and just want the update -make update-force -``` - -Or, manually checkout the changes yourself. - -> ⚠️ **WARNING** ⚠️ -> -> If you customized the files in `data/`, or anything inside `layouts/`, your customization may be overwritten! -> Make sure you have a copy of these changes if you don't want to lose them. - - -```shell -# add Quartz as a remote host -git remote add upstream git@github.com:jackyzha0/quartz.git - -# index and fetch changes -git fetch upstream -git checkout -p upstream/hugo -- layouts .github Makefile assets/js assets/styles/base.scss assets/styles/darkmode.scss config.toml data -``` diff --git a/content/notes/updating.md b/content/notes/updating.md new file mode 100644 index 000000000..290d64756 --- /dev/null +++ b/content/notes/updating.md @@ -0,0 +1,34 @@ +--- +title: "Updating" +aliases: +- update +--- + +Haven't updated Quartz in a while and want all the cool new optimizations? On Unix/Mac systems you can run the following command for a one-line update! This command will show you a log summary of all commits since you last updated, press `q` to acknowledge this. Then, it will show you each change in turn and press `y` to accept the patch or `n` to reject it. Usually you should press `y` for most of these unless it conflicts with existing changes you've made! + +```shell +make update +``` + +Or, if you don't want the interactive parts and just want to force update your local garden (this assumed that you are okay with some of your personalizations been overriden!) + +```shell +make update-force +``` + +Or, manually checkout the changes yourself. + +> ⚠️ **WARNING** ⚠️ +> +> If you customized the files in `data/`, or anything inside `layouts/`, your customization may be overwritten! +> Make sure you have a copy of these changes if you don't want to lose them. + + +```shell +# add Quartz as a remote host +git remote add upstream git@github.com:jackyzha0/quartz.git + +# index and fetch changes +git fetch upstream +git checkout -p upstream/hugo -- layouts .github Makefile assets/js assets/styles/base.scss assets/styles/darkmode.scss config.toml data +``` From 2b0482ae4c5ef7d5c7cc5d33419c1fb440c0238a Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 29 Jun 2022 17:03:41 -0700 Subject: [PATCH 075/122] docs: fix page weight --- content/notes/config.md | 4 +++- content/notes/editing.md | 2 +- content/notes/hosting.md | 2 +- content/notes/obsidian.md | 2 +- content/notes/preview changes.md | 4 +++- content/notes/setup.md | 2 +- 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/content/notes/config.md b/content/notes/config.md index 6e18073cc..320a16d97 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -2,7 +2,7 @@ title: "Configuration" tags: - setup -weight: 5 +weight: 0 --- ## Configuration @@ -180,3 +180,5 @@ defaultContentLanguage = 'ar' title = 'مدونتي' weight = 1 ``` + +[[setup]] \ No newline at end of file diff --git a/content/notes/editing.md b/content/notes/editing.md index af7dd7712..53f537c80 100644 --- a/content/notes/editing.md +++ b/content/notes/editing.md @@ -2,7 +2,7 @@ title: "Editing Content in Quartz" tags: - setup -weight: 1 +weight: -4 --- ## Editing diff --git a/content/notes/hosting.md b/content/notes/hosting.md index adda82d44..d46aff65c 100644 --- a/content/notes/hosting.md +++ b/content/notes/hosting.md @@ -2,7 +2,7 @@ title: "Deploying Quartz to the Web" tags: - setup -weight: 4 +weight: -1 --- ## GitHub Pages diff --git a/content/notes/obsidian.md b/content/notes/obsidian.md index 66cd78d9e..c709a70d7 100644 --- a/content/notes/obsidian.md +++ b/content/notes/obsidian.md @@ -2,7 +2,7 @@ title: "Obsidian Vault Integration" tags: - setup -weight: 2 +weight: -3 --- ## Setup diff --git a/content/notes/preview changes.md b/content/notes/preview changes.md index 3130c58ed..d7e2770eb 100644 --- a/content/notes/preview changes.md +++ b/content/notes/preview changes.md @@ -1,6 +1,8 @@ --- title: "Preview Changes" -weight: 3 +tags: +- setup +weight: -2 --- If you'd like to preview what your Quartz site looks like before deploying it to the internet, here's exactly how to do that! diff --git a/content/notes/setup.md b/content/notes/setup.md index fffb0fb25..12df750ee 100644 --- a/content/notes/setup.md +++ b/content/notes/setup.md @@ -2,7 +2,7 @@ title: "Setup" tags: - setup -weight: 0 +weight: -5 --- ## Making your own Quartz From e884f4927f3e48285ca6689507f5e0f61072de04 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 29 Jun 2022 17:17:53 -0700 Subject: [PATCH 076/122] fix: anchor formatting (closes #141) --- content/notes/config.md | 4 +--- content/notes/editing.md | 2 +- layouts/partials/textprocessing.html | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/content/notes/config.md b/content/notes/config.md index 320a16d97..2c1e352f8 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -179,6 +179,4 @@ defaultContentLanguage = 'ar' languagedirection = 'rtl' title = 'مدونتي' weight = 1 -``` - -[[setup]] \ No newline at end of file +``` \ No newline at end of file diff --git a/content/notes/editing.md b/content/notes/editing.md index 53f537c80..4aaf58563 100644 --- a/content/notes/editing.md +++ b/content/notes/editing.md @@ -34,7 +34,7 @@ You can also use wikilinks if that is what you are more comfortable with! ### Front Matter Hugo is picky when it comes to metadata for files. Make sure that your title is double-quoted and that you have a title defined at the top of your file like so. You can also add tags here as well. -```markdown +```yaml --- title: "Example Title" tags: diff --git a/layouts/partials/textprocessing.html b/layouts/partials/textprocessing.html index 8e8c99917..56e2e8bab 100644 --- a/layouts/partials/textprocessing.html +++ b/layouts/partials/textprocessing.html @@ -39,7 +39,7 @@ {{$reference := split $path "#"}} {{$title := index $reference 0}} {{$block := default "" (index $reference 1)}} - {{$block = strings.TrimRight "/" (cond (eq $block "") $block (printf "#%s" $block))}} + {{$block = strings.TrimRight "/" (cond (eq $block "") $block (printf "#%s" $block)) | urlize | lower}} {{$href := strings.TrimRight "/" ($page.GetPage $title).RelPermalink}} {{$display := default $title (index $split 1)}} {{if not $href}} @@ -54,7 +54,7 @@ {{end}} {{end}} -{{/* Add copyable anchors */}} +{{/* Add jumpable anchors */}} {{ $content = $content | replaceRE "()(.+)()" `${1}# ${3}${4}` }} {{ $content | safeHTML }} From 8b2fba895aa804e895eaa02a622f318113a35663 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 29 Jun 2022 17:34:05 -0700 Subject: [PATCH 077/122] feat: image scaling (closes #131) --- assets/styles/base.scss | 2 +- content/notes/hosting.md | 6 +++++- layouts/partials/textprocessing.html | 6 ++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 1c353f338..776f32d77 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -85,7 +85,7 @@ table { } img { - width: 100%; + max-width: 100%; border-radius: 3px; margin: 1em 0; } diff --git a/content/notes/hosting.md b/content/notes/hosting.md index d46aff65c..8db274666 100644 --- a/content/notes/hosting.md +++ b/content/notes/hosting.md @@ -3,9 +3,11 @@ title: "Deploying Quartz to the Web" tags: - setup weight: -1 +aliases: +- hosting --- -## GitHub Pages +## Hosting on GitHub Pages Quartz is designed to be effortless to deploy. If you forked and cloned Quartz directly from the repository, everything should already be good to go! Follow the steps below. ### Enable GitHub Actions @@ -13,6 +15,8 @@ By default, GitHub disables workflows from running automatically on Forked Repos ![Enable GitHub Actions](notes/images/github-actions.png)*Enable GitHub Actions* +![[notes/images/github-actions.png|200]] + ### Enable GitHub Pages Head to the 'Settings' tab of your forked repository and go to the 'Pages' tab. diff --git a/layouts/partials/textprocessing.html b/layouts/partials/textprocessing.html index 56e2e8bab..dfb0ff2ef 100644 --- a/layouts/partials/textprocessing.html +++ b/layouts/partials/textprocessing.html @@ -27,10 +27,8 @@ {{$inner := . | strings.TrimPrefix "![[" | strings.TrimSuffix "]]" }} {{$split := split $inner "|"}} {{$path := index $split 0 | relURL}} - {{$reference := split $path "#"}} - {{$title := index $reference 0}} - {{$display := default $title (index $split 1)}} - {{$img := printf "" $path $display}} + {{$width := index $split 1}} + {{$img := printf "" $path (default "auto" $width)}} {{$content = replace $content . $img}} {{else}} {{$inner := . | strings.TrimPrefix "[[" | strings.TrimSuffix "]]" }} From 0896814959e912cabaf9ec83bc0a3eb77d152842 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 29 Jun 2022 17:35:29 -0700 Subject: [PATCH 078/122] docs: remove test image from hosting --- content/notes/hosting.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/content/notes/hosting.md b/content/notes/hosting.md index 8db274666..70f9d04cf 100644 --- a/content/notes/hosting.md +++ b/content/notes/hosting.md @@ -15,8 +15,6 @@ By default, GitHub disables workflows from running automatically on Forked Repos ![Enable GitHub Actions](notes/images/github-actions.png)*Enable GitHub Actions* -![[notes/images/github-actions.png|200]] - ### Enable GitHub Pages Head to the 'Settings' tab of your forked repository and go to the 'Pages' tab. From 8d7a7b712f5a4ee49e3687de8fb00f76d7571368 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Fri, 1 Jul 2022 11:02:42 -0700 Subject: [PATCH 079/122] fix: non-SPA fn defs (closes #154) --- layouts/partials/head.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index a364cca2e..d0630a20d 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -127,8 +127,11 @@ navigate: (url) => (window.location.href = url), prefetch: () => {}, } - init() - render() + + window.addEventListener("DOMContentLoaded", () => { + init() + render() + }) {{end}} From d3e20b8b94c9229e94fccbe54c867efde6847c6e Mon Sep 17 00:00:00 2001 From: Geoffrey Garrett Date: Fri, 1 Jul 2022 20:03:52 +0200 Subject: [PATCH 080/122] Added optional rendering of code block titles (#148) --- assets/js/code-title.js | 13 +++ assets/js/darkmode.js | 12 ++- assets/styles/_dark_syntax.scss | 85 +++++++++++++++++++ assets/styles/_light_syntax.scss | 85 +++++++++++++++++++ assets/styles/code-title.scss | 20 +++++ assets/styles/syntax.scss | 139 +++++++++++-------------------- content/notes/config.md | 44 ++++++++-- data/config.yaml | 1 + layouts/partials/head.html | 24 +++++- 9 files changed, 321 insertions(+), 102 deletions(-) create mode 100644 assets/js/code-title.js create mode 100644 assets/styles/_dark_syntax.scss create mode 100644 assets/styles/_light_syntax.scss create mode 100644 assets/styles/code-title.scss diff --git a/assets/js/code-title.js b/assets/js/code-title.js new file mode 100644 index 000000000..698edc9b6 --- /dev/null +++ b/assets/js/code-title.js @@ -0,0 +1,13 @@ + +function addTitleToCodeBlocks() { + var els = document.getElementsByClassName("highlight"); + for (var i = 0; i < els.length; i++) { + if (els[i].title.length) { + let div = document.createElement("div"); + if (els[i].getElementsByClassName("code-title").length) continue; + div.textContent=els[i].title; + div.classList.add("code-title") + els[i].insertBefore(div, els[i].firstChild); + } + } +}; diff --git a/assets/js/darkmode.js b/assets/js/darkmode.js index d95a281ac..11ce15f72 100644 --- a/assets/js/darkmode.js +++ b/assets/js/darkmode.js @@ -1,18 +1,26 @@ const userPref = window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark' const currentTheme = localStorage.getItem('theme') ?? userPref +const syntaxTheme = document.querySelector("#theme-link"); + + +{{ $darkSyntax := resources.Get "styles/_dark_syntax.scss" | resources.ToCSS (dict "outputStyle" "compressed") | resources.Fingerprint "md5" | resources.Minify }} +{{ $lightSyntax := resources.Get "styles/_light_syntax.scss" | resources.ToCSS (dict "outputStyle" "compressed") | resources.Fingerprint "md5" | resources.Minify }} if (currentTheme) { document.documentElement.setAttribute('saved-theme', currentTheme); + (currentTheme === 'dark') ? syntaxTheme.href = '{{ $darkSyntax.Permalink }}' : syntaxTheme.href = '{{ $lightSyntax.Permalink }}'; } const switchTheme = (e) => { if (e.target.checked) { - document.documentElement.setAttribute('saved-theme', 'dark') - localStorage.setItem('theme', 'dark') + document.documentElement.setAttribute('saved-theme', 'dark'); + localStorage.setItem('theme', 'dark'); + syntaxTheme.href = '{{ $darkSyntax.Permalink }}'; } else { document.documentElement.setAttribute('saved-theme', 'light') localStorage.setItem('theme', 'light') + syntaxTheme.href = '{{ $lightSyntax.Permalink }}'; } } diff --git a/assets/styles/_dark_syntax.scss b/assets/styles/_dark_syntax.scss new file mode 100644 index 000000000..9d2019a8a --- /dev/null +++ b/assets/styles/_dark_syntax.scss @@ -0,0 +1,85 @@ +/* Background */ .bg { color: #f8f8f2; background-color: #282a36; } +/* PreWrapper */ .chroma { color: #f8f8f2; background-color: #282a36; } +/* Other */ .chroma .x { } +/* Error */ .chroma .err { } +/* CodeLine */ .chroma .cl { } +/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } +/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } +/* LineHighlight */ .chroma .hl { background-color: #ffffcc } +/* LineNumbersTable */ .chroma .lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } +/* LineNumbers */ .chroma .ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } +/* Line */ .chroma .line { display: flex; } +/* 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: #ff5555 } +/* GenericEmph */ .chroma .ge { text-decoration: underline } +/* GenericError */ .chroma .gr { } +/* GenericHeading */ .chroma .gh { font-weight: bold } +/* GenericInserted */ .chroma .gi { color: #50fa7b; 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 { } diff --git a/assets/styles/_light_syntax.scss b/assets/styles/_light_syntax.scss new file mode 100644 index 000000000..1927b5751 --- /dev/null +++ b/assets/styles/_light_syntax.scss @@ -0,0 +1,85 @@ +/* Background */ .bg { color: #272822; background-color: #fafafa; } +/* PreWrapper */ .chroma { color: #272822; background-color: #fafafa; } +/* Other */ .chroma .x { } +/* Error */ .chroma .err { color: #960050; background-color: #1e0010 } +/* CodeLine */ .chroma .cl { } +/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } +/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } +/* LineHighlight */ .chroma .hl { background-color: #ffffcc } +/* LineNumbersTable */ .chroma .lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } +/* LineNumbers */ .chroma .ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } +/* Line */ .chroma .line { display: flex; } +/* Keyword */ .chroma .k { color: #00a8c8 } +/* KeywordConstant */ .chroma .kc { color: #00a8c8 } +/* KeywordDeclaration */ .chroma .kd { color: #00a8c8 } +/* KeywordNamespace */ .chroma .kn { color: #f92672 } +/* KeywordPseudo */ .chroma .kp { color: #00a8c8 } +/* KeywordReserved */ .chroma .kr { color: #00a8c8 } +/* KeywordType */ .chroma .kt { color: #00a8c8 } +/* Name */ .chroma .n { color: #111111 } +/* NameAttribute */ .chroma .na { color: #75af00 } +/* NameBuiltin */ .chroma .nb { color: #111111 } +/* NameBuiltinPseudo */ .chroma .bp { color: #111111 } +/* NameClass */ .chroma .nc { color: #75af00 } +/* NameConstant */ .chroma .no { color: #00a8c8 } +/* NameDecorator */ .chroma .nd { color: #75af00 } +/* NameEntity */ .chroma .ni { color: #111111 } +/* NameException */ .chroma .ne { color: #75af00 } +/* NameFunction */ .chroma .nf { color: #75af00 } +/* NameFunctionMagic */ .chroma .fm { color: #111111 } +/* NameLabel */ .chroma .nl { color: #111111 } +/* NameNamespace */ .chroma .nn { color: #111111 } +/* NameOther */ .chroma .nx { color: #75af00 } +/* NameProperty */ .chroma .py { color: #111111 } +/* NameTag */ .chroma .nt { color: #f92672 } +/* NameVariable */ .chroma .nv { color: #111111 } +/* NameVariableClass */ .chroma .vc { color: #111111 } +/* NameVariableGlobal */ .chroma .vg { color: #111111 } +/* NameVariableInstance */ .chroma .vi { color: #111111 } +/* NameVariableMagic */ .chroma .vm { color: #111111 } +/* Literal */ .chroma .l { color: #ae81ff } +/* LiteralDate */ .chroma .ld { color: #d88200 } +/* LiteralString */ .chroma .s { color: #d88200 } +/* LiteralStringAffix */ .chroma .sa { color: #d88200 } +/* LiteralStringBacktick */ .chroma .sb { color: #d88200 } +/* LiteralStringChar */ .chroma .sc { color: #d88200 } +/* LiteralStringDelimiter */ .chroma .dl { color: #d88200 } +/* LiteralStringDoc */ .chroma .sd { color: #d88200 } +/* LiteralStringDouble */ .chroma .s2 { color: #d88200 } +/* LiteralStringEscape */ .chroma .se { color: #8045ff } +/* LiteralStringHeredoc */ .chroma .sh { color: #d88200 } +/* LiteralStringInterpol */ .chroma .si { color: #d88200 } +/* LiteralStringOther */ .chroma .sx { color: #d88200 } +/* LiteralStringRegex */ .chroma .sr { color: #d88200 } +/* LiteralStringSingle */ .chroma .s1 { color: #d88200 } +/* LiteralStringSymbol */ .chroma .ss { color: #d88200 } +/* LiteralNumber */ .chroma .m { color: #ae81ff } +/* LiteralNumberBin */ .chroma .mb { color: #ae81ff } +/* LiteralNumberFloat */ .chroma .mf { color: #ae81ff } +/* LiteralNumberHex */ .chroma .mh { color: #ae81ff } +/* LiteralNumberInteger */ .chroma .mi { color: #ae81ff } +/* LiteralNumberIntegerLong */ .chroma .il { color: #ae81ff } +/* LiteralNumberOct */ .chroma .mo { color: #ae81ff } +/* Operator */ .chroma .o { color: #f92672 } +/* OperatorWord */ .chroma .ow { color: #f92672 } +/* Punctuation */ .chroma .p { color: #111111 } +/* Comment */ .chroma .c { color: #75715e } +/* CommentHashbang */ .chroma .ch { color: #75715e } +/* CommentMultiline */ .chroma .cm { color: #75715e } +/* CommentSingle */ .chroma .c1 { color: #75715e } +/* CommentSpecial */ .chroma .cs { color: #75715e } +/* CommentPreproc */ .chroma .cp { color: #75715e } +/* CommentPreprocFile */ .chroma .cpf { color: #75715e } +/* Generic */ .chroma .g { } +/* GenericDeleted */ .chroma .gd { } +/* GenericEmph */ .chroma .ge { font-style: italic } +/* GenericError */ .chroma .gr { } +/* GenericHeading */ .chroma .gh { } +/* GenericInserted */ .chroma .gi { } +/* GenericOutput */ .chroma .go { } +/* GenericPrompt */ .chroma .gp { } +/* GenericStrong */ .chroma .gs { font-weight: bold } +/* GenericSubheading */ .chroma .gu { } +/* GenericTraceback */ .chroma .gt { } +/* GenericUnderline */ .chroma .gl { } +/* TextWhitespace */ .chroma .w { } diff --git a/assets/styles/code-title.scss b/assets/styles/code-title.scss new file mode 100644 index 000000000..11b088a79 --- /dev/null +++ b/assets/styles/code-title.scss @@ -0,0 +1,20 @@ +.code-title { + color: var(--primary) ; + font-family: monospace; + width: max-content; + overflow-x: auto; + display: inline-block; + vertical-align: middle; + font-weight: normal; + line-height: 1em; + position: relative; + padding: 0.5em 0.6em 0.6em; // + 1.2 em + max-width: calc(100% - 1.2em); // (-1.2 em) fits article width exactly + margin-bottom: -0.2em; + z-index: -1; + border-top-left-radius: 0.3em; + border-top-right-radius: 0.3em; + font-size: 0.9em; + background-color: var(--lightgray); + filter: hue-rotate(-30deg) contrast(1.0) opacity(0.8); +} \ No newline at end of file diff --git a/assets/styles/syntax.scss b/assets/styles/syntax.scss index bada47ab5..fbea72a44 100644 --- a/assets/styles/syntax.scss +++ b/assets/styles/syntax.scss @@ -1,99 +1,58 @@ -/* Background */ .chroma { color: #f8f8f2; background-color: #282a36; overflow: hidden } -/* 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 { } +// Overrides +/* Background */ +.chroma { + overflow: hidden !important; + background-color: var(--lightgray) !important; +} + +/* LineTable */ +.chroma .lntable { + width: auto !important; + overflow: auto !important; + display: block !important; +} + +/* LineHighlight */ +.chroma .hl { + display: block !important; + width: 100% !important; +} + +/* LineNumbersTable */ +.chroma .lnt { + margin-right: 0.0em !important; + padding: 0 0.0em 0 0.0em !important; +} + +/* LineNumbers */ +.chroma .ln { + margin-right: 0.0em !important; + padding: 0 0.0em 0 0.0em !important; +} + +/* GenericDeleted */ +.chroma .gd { + color: #8b080b !important; +} + +/* GenericInserted */ +.chroma .gi { + font-weight: bold !important; +} .lntd:first-of-type > .chroma { - padding-right: 0; + padding-right: 0 !important; } .chroma code { font-family: 'Fira Code' !important; - font-size: 0.85em; - line-height: 1em; - background: none; - padding: 0; + font-size: 0.85em !important; + line-height: 2em !important; + background: none !important; + padding: 0 !important; } .chroma { - border-radius: 3px; - margin: 0; -} \ No newline at end of file + border-radius: 3px !important; + margin: 0 !important; +} diff --git a/content/notes/config.md b/content/notes/config.md index 2c1e352f8..076857ed4 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -8,9 +8,9 @@ weight: 0 ## Configuration Quartz is designed to be extremely configurable. You can find the bulk of the configuration scattered throughout the repository depending on how in-depth you'd like to get. -The majority of configuration can be be found under `data/config.yaml`. An annotated example configuration is shown below. +The majority of configuration can be found under `data/config.yaml`. An annotated example configuration is shown below. -```yaml +```yaml {title="data/config.yaml"} # The name to display in the footer name: Jacky Zhao @@ -25,6 +25,9 @@ openToc: false # whether to display on-hover link preview cards enableLinkPreview: true +# whether to render titles for code blocks +enableCodeBlockTitle: true + # whether to try to process Latex enableLatex: true @@ -60,12 +63,34 @@ links: link: https://github.com/jackyzha0 ``` +### Code Block Titles + +To add code block titles with Quartz: + +1. Ensure that code block titles are enabled in Quartz's configuration: + + ```yaml {title="data/config.yaml", linenos=false} + enableCodeBlockTitle: true + ``` + +2. Add the `title` attribute to the desired [code block + fence](https://gohugo.io/content-management/syntax-highlighting/#highlighting-in-code-fences): + + ```markdown {linenos=false} + ```yaml {title="data/config.yaml"} + enableCodeBlockTitle: true # example from step 1 + ``` + ``` + +**Note** that if `{title=}` is included, and code block titles are not +enabled, no errors will occur and the title attribute will be ignored. + ### HTML Favicons If you would like to customize the favicons of your quartz-based website, you can add them to the `data/config.yaml` file. The **default** without any set `favicon` key is: -```html +```html {title="layouts/partials/head.html", linenostart=15} ``` @@ -73,7 +98,7 @@ The default can be overridden by defining a value to the `favicon` key in your `data/config.yaml` file. Here is a `List[Dictionary]` example format, which is equivalent to the default: -```yaml +```yaml {title="data/config.yaml", linenos=false} favicon: - { rel: "shortcut icon", href: "icon.png", type: "image/png" } # - { ... } # Repeat for each additional favicon you want to add @@ -85,7 +110,7 @@ If you plan to add multiple favicons generated by a website (see list below), it may be easier to define it as HTML. Here is an example which appends the **Apple touch icon** to quartz's default favicon: -```yaml +```yaml {title="data/config.yaml", linenos=false} favicon: | @@ -102,7 +127,8 @@ attribute, are relative to the `static/` directory. ### Graph View To customize the Interactive Graph view, you can poke around `data/graphConfig.yaml`. -```yaml + +```yaml {title="data/graphConfig.yaml"} # if true, a Global Graph will be shown on home page with full width, no backlink. # A different set of Local Graphs will be shown on sub pages. # if false, Local Graph will be default on every page as usual @@ -128,10 +154,10 @@ localGraph: # how strongly nodes should repel each other repelForce: 2 - # how strongly should nodes be attracted to the center of gravity + # how strongly should nodes be attracted to the center of gravity centerForce: 1 - # what the default link length should be + # what the default link length should be linkDistance: 1 # how big the node labels should be @@ -179,4 +205,4 @@ defaultContentLanguage = 'ar' languagedirection = 'rtl' title = 'مدونتي' weight = 1 -``` \ No newline at end of file +``` diff --git a/data/config.yaml b/data/config.yaml index cae94ef45..e55035a08 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -3,6 +3,7 @@ enableToc: true openToc: false enableLinkPreview: true enableLatex: true +enableCodeBlockTitle: true enableSPA: true enableFooter: true enableContextualBacklinks: true diff --git a/layouts/partials/head.html b/layouts/partials/head.html index d0630a20d..e3eebbfee 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -36,7 +36,11 @@ {{$finalCss := $css | resources.Concat "styles.css" | resources.Fingerprint "md5" | resources.Minify }} - {{ $darkMode := resources.Get "js/darkmode.js" | resources.Fingerprint "md5" | resources.Minify }} + {{$lightSyntax := resources.Get "styles/_light_syntax.scss" | resources.ToCSS (dict "outputStyle" "compressed") | resources.Fingerprint "md5" | resources.Minify }} + + + + {{ $darkMode := resources.Get "js/darkmode.js" | resources.ExecuteAsTemplate "js/darkmode.js" . | resources.Fingerprint "md5" | resources.Minify }} {{partial "katex.html" .}} @@ -44,6 +48,12 @@ resources.Minify }} + + {{ if $.Site.Data.config.enableCodeBlockTitle }} + {{ $codeTitle := resources.Get "js/code-title.js" | resources.Fingerprint "md5" | resources.Minify }} + + {{end}} + {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint "md5" | resources.Minify | }} {{$contentIndex := resources.Get @@ -75,6 +85,10 @@ const pathWindow = window.location.pathname; const isHome = pathBase == pathWindow; + {{if $.Site.Data.config.enableSPA -}} + addTitleToCodeBlocks(); + {{ end }} + {{if $.Site.Data.config.enableFooter}} const container = document.getElementById("graph-container") // retry if the graph is not ready @@ -92,6 +106,7 @@ {{end}} + {{if $.Site.Data.config.enableLinkPreview}} initPopover( {{strings.TrimRight "/" .Site.BaseURL }}, @@ -103,6 +118,13 @@ const init = (doc = document) => { // NOTE: everything within this callback will be executed for initial page navigation. This is a good place to put JavaScript that only replaces DOM nodes. + {{if $.Site.Data.config.enableCodeBlockTitle -}} + {{if $.Site.Data.config.enableSPA -}} + addTitleToCodeBlocks(); + {{ else }} + window.addEventListener("DOMContentLoaded", addTitleToCodeBlocks); + {{- end -}} + {{- end -}} {{if $.Site.Data.config.enableLatex}} renderMathInElement(doc.body, { delimiters: [ From eda370334a3798070c2f79ec38021edb3b33a84f Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Fri, 1 Jul 2022 11:27:50 -0700 Subject: [PATCH 081/122] fix: image scaling for md-style links (closes #155) --- content/notes/hosting.md | 2 +- layouts/_default/_markup/render-image.html | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/content/notes/hosting.md b/content/notes/hosting.md index 70f9d04cf..fffcd653a 100644 --- a/content/notes/hosting.md +++ b/content/notes/hosting.md @@ -66,7 +66,7 @@ Please note that the `cname` field should *not* have any path `e.g. end with /qu [Reference `deploy.yaml` here](https://github.com/jackyzha0/quartz/blob/hugo/.github/workflows/deploy.yaml) -```yaml +```yaml {title=".github/workflows/deploy.yaml"} - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: diff --git a/layouts/_default/_markup/render-image.html b/layouts/_default/_markup/render-image.html index 8dda6a8c0..dbcf732fd 100644 --- a/layouts/_default/_markup/render-image.html +++ b/layouts/_default/_markup/render-image.html @@ -1,8 +1,9 @@ {{$src := .Destination | safeURL }} +{{$width := index (split .Text "|") 1 | default "auto" }} {{$external := strings.HasPrefix $src "http" }} {{- if $external -}} -{{ .Text }} +{{ .Text }} {{- else -}} {{$fixedUrl := (cond (hasPrefix $src "/") $src (print "/" $src)) | urlize}} -{{ .Text }} +{{ .Text }} {{- end -}} From a8137edf247c46ef3a5af78c48bcd299a13c1a7d Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 2 Jul 2022 17:14:17 -0700 Subject: [PATCH 082/122] fix: adjust weird colours for err highlighting --- assets/styles/_light_syntax.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/styles/_light_syntax.scss b/assets/styles/_light_syntax.scss index 1927b5751..d0f452e03 100644 --- a/assets/styles/_light_syntax.scss +++ b/assets/styles/_light_syntax.scss @@ -1,7 +1,7 @@ /* Background */ .bg { color: #272822; background-color: #fafafa; } /* PreWrapper */ .chroma { color: #272822; background-color: #fafafa; } /* Other */ .chroma .x { } -/* Error */ .chroma .err { color: #960050; background-color: #1e0010 } +/* Error */ .chroma .err { } /* CodeLine */ .chroma .cl { } /* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } /* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } From 015ed4cfa2db4636e03debcda0d4201f24346098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aiden=20Bai=20=E7=99=BD=E5=AE=87=E5=BD=A4?= Date: Sat, 2 Jul 2022 19:40:18 -0700 Subject: [PATCH 083/122] Fix `width: auto` for SPA routing (#156) --- assets/js/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/router.js b/assets/js/router.js index b2b6d2119..efaa10e8a 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -3,7 +3,7 @@ import { navigate, prefetch, router, -} from "https://unpkg.com/million@1.11.3/dist/router.mjs" +} from "https://unpkg.com/million@1.11.5/dist/router.mjs" export const attachSPARouting = (init, rerender) => { // Attach SPA functions to the global Million namespace From f54df35767dcda9bc4853decff86d57323593685 Mon Sep 17 00:00:00 2001 From: Geoffrey Garrett Date: Sun, 3 Jul 2022 20:42:35 +0200 Subject: [PATCH 084/122] Copy to clipboard feature for code block (#152) Co-authored-by: Jacky Zhao --- assets/js/clipboard.js | 38 +++++++++++++++++++++++++++++ assets/js/darkmode.js | 2 +- assets/styles/clipboard.scss | 47 ++++++++++++++++++++++++++++++++++++ content/notes/config.md | 21 +++++++++------- data/config.yaml | 1 + layouts/partials/head.html | 19 ++++++++++++--- 6 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 assets/js/clipboard.js create mode 100644 assets/styles/clipboard.scss diff --git a/assets/js/clipboard.js b/assets/js/clipboard.js new file mode 100644 index 000000000..6389330e4 --- /dev/null +++ b/assets/js/clipboard.js @@ -0,0 +1,38 @@ +const svgCopy = + ''; +const svgCheck = + ''; + + +const addCopyButtons = () => { + let els = document.getElementsByClassName("highlight"); + // for each highlight + for (let i = 0; i < els.length; i++) { + if (els[i].getElementsByClassName("clipboard-button").length) continue; + + // find pre > code inside els[i] + let codeBlocks = els[i].getElementsByTagName("code"); + + // line numbers are inside first code block + let lastCodeBlock = codeBlocks[codeBlocks.length - 1]; + const button = document.createElement("button"); + button.className = "clipboard-button"; + button.type = "button"; + button.innerHTML = svgCopy; + // remove every second newline from lastCodeBlock.innerText + button.addEventListener("click", () => { + navigator.clipboard.writeText(lastCodeBlock.innerText.replace(/\n\n/g, "\n")).then( + () => { + button.blur(); + button.innerHTML = svgCheck; + setTimeout(() => (button.innerHTML = svgCopy), 2000); + }, + (error) => (button.innerHTML = "Error") + ); + }); + // find chroma inside els[i] + let chroma = els[i].getElementsByClassName("chroma")[0]; + els[i].insertBefore(button, chroma); + console.log(els[i].lastChild) + } +} diff --git a/assets/js/darkmode.js b/assets/js/darkmode.js index 11ce15f72..8168d77e3 100644 --- a/assets/js/darkmode.js +++ b/assets/js/darkmode.js @@ -8,7 +8,7 @@ const syntaxTheme = document.querySelector("#theme-link"); if (currentTheme) { document.documentElement.setAttribute('saved-theme', currentTheme); - (currentTheme === 'dark') ? syntaxTheme.href = '{{ $darkSyntax.Permalink }}' : syntaxTheme.href = '{{ $lightSyntax.Permalink }}'; + syntaxTheme.href = currentTheme === 'dark' ? '{{ $darkSyntax.Permalink }}' : '{{ $lightSyntax.Permalink }}'; } const switchTheme = (e) => { diff --git a/assets/styles/clipboard.scss b/assets/styles/clipboard.scss new file mode 100644 index 000000000..7989e248c --- /dev/null +++ b/assets/styles/clipboard.scss @@ -0,0 +1,47 @@ +.clipboard-button { + position: absolute; + display: flex; + float: right; + right: 0; + padding: 0.69em; + margin: 0.5em; + color: var(--outlinegray); + border-color: var(--dark); + background-color: var(--lightgray); + filter: contrast(1.1); + border: 2px solid; + border-radius: 6px; + font-size: 0.8em; + z-index: 1; + opacity: 0; + transition: 0.12s; + + & > svg { + fill: var(--light); + filter: contrast(0.3); + } + + &:hover { + cursor: pointer; + border-color: var(--primary); + + & > svg { + fill: var(--primary); + } + } + + &:focus { + outline: 0; + } +} + +.highlight { + position: relative; + + &:hover > .clipboard-button { + opacity: 1; + transition: 0.2s; + } +} + + diff --git a/content/notes/config.md b/content/notes/config.md index 076857ed4..056ae36a3 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -28,12 +28,15 @@ enableLinkPreview: true # whether to render titles for code blocks enableCodeBlockTitle: true +# whether to render copy buttons for code blocks +enableCodeBlockCopy: true + # whether to try to process Latex enableLatex: true # whether to enable single-page-app style rendering -# this prevents flahses of unstyled content and overall improves -# smoothness of quartz. More info in issue #109 on GitHub +# this prevents flashes of unstyled content and improves +# smoothness of Quartz. More info in issue #109 on GitHub enableSPA: true # whether to render a footer @@ -83,10 +86,10 @@ To add code block titles with Quartz: ``` **Note** that if `{title=}` is included, and code block titles are not -enabled, no errors will occur and the title attribute will be ignored. +enabled, no errors will occur, and the title attribute will be ignored. ### HTML Favicons -If you would like to customize the favicons of your quartz-based website, you +If you would like to customize the favicons of your Quartz-based website, you can add them to the `data/config.yaml` file. The **default** without any set `favicon` key is: @@ -95,7 +98,7 @@ can add them to the `data/config.yaml` file. The **default** without any set ``` The default can be overridden by defining a value to the `favicon` key in your -`data/config.yaml` file. Here is a `List[Dictionary]` example format, which is +`data/config.yaml` file. For example, here is a `List[Dictionary]` example format, which is equivalent to the default: ```yaml {title="data/config.yaml", linenos=false} @@ -108,7 +111,7 @@ In this format, the keys are identical to their HTML representations. If you plan to add multiple favicons generated by a website (see list below), it may be easier to define it as HTML. Here is an example which appends the -**Apple touch icon** to quartz's default favicon: +**Apple touch icon** to Quartz's default favicon: ```yaml {title="data/config.yaml", linenos=false} favicon: | @@ -118,7 +121,7 @@ favicon: | This second favicon will now be used as a web page icon when someone adds your webpage to the home screen of their Apple device. If you are interested in more -information about the current, and past, standards of favicons, you can read +information about the current and past standards of favicons, you can read [this article](https://www.emergeinteractive.com/insights/detail/the-essentials-of-favicons/). **Note** that all generated favicon paths, defined by the `href` @@ -136,7 +139,7 @@ enableGlobalGraph: false ### Local Graph ### localGraph: - # whether automatically generate a legend + # whether automatically generate a legend enableLegend: false # whether to allow dragging nodes in the graph @@ -181,7 +184,7 @@ paths: Want to go even more in-depth? You can add custom CSS styling and change existing colours through editing `assets/styles/custom.scss`. If you'd like to target specific parts of the site, you can add ids and classes to the HTML partials in `/layouts/partials`. ### Partials -Partials are what dictate what actually gets rendered to the page. Want to change how pages are styled and structured? You can edit the appropriate layout in `/layouts`. +Partials are what dictate what gets rendered to the page. Want to change how pages are styled and structured? You can edit the appropriate layout in `/layouts`. For example, the structure of the home page can be edited through `/layouts/index.html`. To customize the footer, you can edit `/layouts/partials/footer.html` diff --git a/data/config.yaml b/data/config.yaml index e55035a08..7ef35a540 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -4,6 +4,7 @@ openToc: false enableLinkPreview: true enableLatex: true enableCodeBlockTitle: true +enableCodeBlockCopy: true enableSPA: true enableFooter: true enableContextualBacklinks: true diff --git a/layouts/partials/head.html b/layouts/partials/head.html index e3eebbfee..7dfbd50ca 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -54,6 +54,13 @@ {{end}} + {{ if $.Site.Data.config.enableCodeBlockCopy }} + {{ $clipboard := resources.Get "js/clipboard.js" | resources.Fingerprint "md5" | resources.Minify }} + {{ if (findRE " + {{ end }} + {{ end }} + {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint "md5" | resources.Minify | }} {{$contentIndex := resources.Get @@ -85,6 +92,10 @@ const pathWindow = window.location.pathname; const isHome = pathBase == pathWindow; + {{if $.Site.Data.config.enableCodeBlockCopy -}} + addCopyButtons(); + {{ end }} + {{if $.Site.Data.config.enableSPA -}} addTitleToCodeBlocks(); {{ end }} @@ -118,12 +129,12 @@ const init = (doc = document) => { // NOTE: everything within this callback will be executed for initial page navigation. This is a good place to put JavaScript that only replaces DOM nodes. + {{if $.Site.Data.config.enableCodeBlockCopy -}} + addCopyButtons(); + {{ end }} + {{if $.Site.Data.config.enableCodeBlockTitle -}} - {{if $.Site.Data.config.enableSPA -}} addTitleToCodeBlocks(); - {{ else }} - window.addEventListener("DOMContentLoaded", addTitleToCodeBlocks); - {{- end -}} {{- end -}} {{if $.Site.Data.config.enableLatex}} renderMathInElement(doc.body, { From aaf31f419eb167dbb7582fb103be29f0bef95ba9 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 3 Jul 2022 11:50:13 -0700 Subject: [PATCH 085/122] fix: copy code block logic for non code pages --- layouts/partials/head.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 7dfbd50ca..0890983b4 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -56,9 +56,7 @@ {{ if $.Site.Data.config.enableCodeBlockCopy }} {{ $clipboard := resources.Get "js/clipboard.js" | resources.Fingerprint "md5" | resources.Minify }} - {{ if (findRE " - {{ end }} + {{ end }} From 25a4d3b6e17c2a5f6a935446ea97d06a323f71f6 Mon Sep 17 00:00:00 2001 From: rphla <101242699+rphla@users.noreply.github.com> Date: Wed, 6 Jul 2022 06:39:29 +0800 Subject: [PATCH 086/122] Add GitHub "edit" button (#157) --- data/config.yaml | 2 ++ layouts/_default/single.html | 3 ++- layouts/partials/github.html | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 layouts/partials/github.html diff --git a/data/config.yaml b/data/config.yaml index 7ef35a540..ce9ff0ab6 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -9,6 +9,8 @@ enableSPA: true enableFooter: true enableContextualBacklinks: true enableRecentNotes: false +enableGitHubEdit: false +GHlink: https://github.com/jackyzha0/quartz/tree/hugo/content description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, Wikilink support, backlinks, local graph, tags, and link previews. diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 91eda290b..06507a705 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -15,7 +15,8 @@
    {{if .Title}}

    {{ .Title }}

    {{end}}

    - Last updated {{if ne .Date .Lastmod}}{{ .Lastmod.Format "January 2, 2006" }}{{else}}Unknown{{end}} + Last updated {{if ne .Date .Lastmod}}{{ .Lastmod.Format "January 2, 2006" }}{{else}}Unknown{{end}}. + {{ partial "github.html" . }}

      {{ range (.GetTerms "tags") }} diff --git a/layouts/partials/github.html b/layouts/partials/github.html new file mode 100644 index 000000000..87a4429dd --- /dev/null +++ b/layouts/partials/github.html @@ -0,0 +1,3 @@ +{{if $.Site.Data.config.enableGitHubEdit} +Edit Source +{{end}} From 74993d19b72aee78e89b0b13b8f1d4a72fe5fe29 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Tue, 5 Jul 2022 15:42:57 -0700 Subject: [PATCH 087/122] docs + fix: broken partial and description of enableGitHubEdit --- content/notes/config.md | 5 +++++ data/config.yaml | 2 +- layouts/partials/github.html | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/content/notes/config.md b/content/notes/config.md index 056ae36a3..e29afda34 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -49,6 +49,11 @@ enableContextualBacklinks: true # whether to show a section of recent notes on the home page enableRecentNotes: false +# whether to display and 'edit' button next to the last edited field +# that links to github +enableGitHubEdit: false +GitHubLink: https://github.com/jackyzha0/quartz/tree/hugo/content + # page description used for SEO description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, diff --git a/data/config.yaml b/data/config.yaml index ce9ff0ab6..bae38dbaf 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -10,7 +10,7 @@ enableFooter: true enableContextualBacklinks: true enableRecentNotes: false enableGitHubEdit: false -GHlink: https://github.com/jackyzha0/quartz/tree/hugo/content +GitHubLink: https://github.com/jackyzha0/quartz/tree/hugo/content description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, Wikilink support, backlinks, local graph, tags, and link previews. diff --git a/layouts/partials/github.html b/layouts/partials/github.html index 87a4429dd..a7b3d13ec 100644 --- a/layouts/partials/github.html +++ b/layouts/partials/github.html @@ -1,3 +1,3 @@ -{{if $.Site.Data.config.enableGitHubEdit} -Edit Source +{{if $.Site.Data.config.enableGitHubEdit}} +Edit Source {{end}} From b7a619bbd73f9220f8c1fcbad203792c78343464 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Tue, 12 Jul 2022 14:37:10 -0700 Subject: [PATCH 088/122] fix: tabsize not being respected --- assets/styles/syntax.scss | 4 ++++ config.toml | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/assets/styles/syntax.scss b/assets/styles/syntax.scss index fbea72a44..14153c9a0 100644 --- a/assets/styles/syntax.scss +++ b/assets/styles/syntax.scss @@ -56,3 +56,7 @@ border-radius: 3px !important; margin: 0 !important; } + +pre.chroma { + -moz-tab-size:4;-o-tab-size:4;tab-size:4; +} diff --git a/config.toml b/config.toml index 94c2f9b40..a545ed815 100644 --- a/config.toml +++ b/config.toml @@ -1,7 +1,6 @@ baseURL = "https://quartz.jzhao.xyz/" languageCode = "en-us" googleAnalytics = "G-XYFD95KB4J" -pygmentsUseClasses = true relativeURLs = false disablePathToLower = true ignoreFiles = [ @@ -18,6 +17,7 @@ enableGitInfo = true ordered = true startLevel = 2 [markup.highlight] + noClasses = false anchorLineNos = false codeFences = true guessSyntax = true @@ -27,7 +27,6 @@ enableGitInfo = true lineNos = true lineNumbersInTable = true style = "dracula" - tabWidth = 4 [frontmatter] lastmod = ["lastmod", ":git", "date", "publishDate"] publishDate = ["publishDate", "date"] From c1b8fe1221e3367f0632ce43f602e811c0fd0284 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 13 Jul 2022 14:32:32 -0700 Subject: [PATCH 089/122] feat: restyle search icon --- assets/styles/base.scss | 19 +++++++++++++++---- layouts/_default/section.html | 7 +------ layouts/_default/single.html | 9 ++------- layouts/_default/taxonomy.html | 7 +------ layouts/_default/term.html | 7 +------ layouts/index.html | 7 +------ layouts/partials/header.html | 10 ++++++++++ 7 files changed, 31 insertions(+), 35 deletions(-) create mode 100644 layouts/partials/header.html diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 776f32d77..4426abb06 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -24,7 +24,6 @@ h1, h2, h3, h4, h5, h6, ol, ul, thead { opacity: 0.3; transition: opacity 0.3s ease; color: var(--secondary); - } p, ul, text { @@ -381,11 +380,24 @@ header { flex: 1 1 auto; } - & > svg { + #search-icon { + background-color: var(--lightgray); + border-radius: 4px; + height: 2em; + display: flex; + align-items: center; + cursor: pointer; + & > p { + display: inline; + padding-left: 0.5em; + } + } + + & svg { cursor: pointer; width: 18px; min-width: 18px; - margin: 0 1em; + margin: 0 0.5em; &:hover .search-path { stroke: var(--tertiary); @@ -592,4 +604,3 @@ header { } } - diff --git a/layouts/_default/section.html b/layouts/_default/section.html index abdf0b05c..2fc714439 100644 --- a/layouts/_default/section.html +++ b/layouts/_default/section.html @@ -6,12 +6,7 @@ {{partial "search.html" .}}
      -
      -

      {{ .Site.Data.config.page_title }}

      - Search IconIcon to open search -
      - {{partial "darkmode.html" .}} -
      + {{partial "header.html" .}}

      All {{.Title}}

      {{partial "page-list.html" .Paginator.Pages.ByLastmod.Reverse }} diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 06507a705..7c2ab10f5 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -6,13 +6,8 @@ {{partial "search.html" .}}
      -
      -

      {{ .Site.Data.config.page_title }}

      - Search IconIcon to open search -
      - {{partial "darkmode.html" .}} -
      -
      + {{partial "header.html" .}} +
      {{if .Title}}

      {{ .Title }}

      {{end}}

      Last updated {{if ne .Date .Lastmod}}{{ .Lastmod.Format "January 2, 2006" }}{{else}}Unknown{{end}}. diff --git a/layouts/_default/taxonomy.html b/layouts/_default/taxonomy.html index e0a1e876c..8f86b648f 100644 --- a/layouts/_default/taxonomy.html +++ b/layouts/_default/taxonomy.html @@ -6,12 +6,7 @@ {{partial "search.html" .}}

      -
      -

      {{ .Site.Data.config.page_title }}

      - Search IconIcon to open search -
      - {{partial "darkmode.html" .}} -
      + {{partial "header.html" .}}

      All {{.Title}}

      diff --git a/layouts/_default/term.html b/layouts/_default/term.html index 58f024bcc..abddc07b4 100644 --- a/layouts/_default/term.html +++ b/layouts/_default/term.html @@ -6,12 +6,7 @@ {{partial "search.html" .}}
      -
      -

      {{ .Site.Data.config.page_title }}

      - Search IconIcon to open search -
      - {{partial "darkmode.html" .}} -
      + {{partial "header.html" .}}

      Tag: {{.Title | humanize}}

      {{partial "page-list.html" .Paginator.Pages}} diff --git a/layouts/index.html b/layouts/index.html index 505361420..c7871e9f6 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -6,12 +6,7 @@ {{partial "search.html" .}}
      -
      -

      {{if .Title}}{{ .Title }}{{else}}Untitled{{end}}

      - Search IconIcon to open search -
      - {{partial "darkmode.html" .}} -
      + {{partial "header.html" .}}
      {{partial "toc.html" .}} {{partial "textprocessing.html" . }} diff --git a/layouts/partials/header.html b/layouts/partials/header.html new file mode 100644 index 000000000..773e0684b --- /dev/null +++ b/layouts/partials/header.html @@ -0,0 +1,10 @@ +
      +

      {{ .Site.Data.config.page_title }}

      +
      +
      +

      Search

      + Search IconIcon to open search +
      + {{partial "darkmode.html" .}} +
      + From ffe22689eb43f42afc2d6bcf9b8b190b19a7e5d1 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 13 Jul 2022 15:01:50 -0700 Subject: [PATCH 090/122] feat: use floating-ui for better popover positioning --- assets/js/popover.js | 11 +++++++++++ assets/styles/base.scss | 9 ++------- layouts/partials/head.html | 3 +++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/assets/js/popover.js b/assets/js/popover.js index 494cd84e1..8eb637d6f 100644 --- a/assets/js/popover.js +++ b/assets/js/popover.js @@ -46,7 +46,18 @@ function initPopover(baseURL, useContextualBacklinks, renderLatex) { throwOnError: false }) } + li.addEventListener("mouseover", () => { + // fix tooltip positioning + window.FloatingUIDOM.computePosition(li, el, { + middleware: [window.FloatingUIDOM.offset(15), window.FloatingUIDOM.inline(), window.FloatingUIDOM.shift()], + }).then(({ x, y }) => { + Object.assign(el.style, { + left: `${x}px`, + top: `${y}px`, + }) + }) + el.classList.add("visible") }) li.addEventListener("mouseout", () => { diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 4426abb06..8898ec39b 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -389,7 +389,7 @@ header { cursor: pointer; & > p { display: inline; - padding-left: 0.5em; + padding: 0 0.5em 0 1em; } } @@ -534,12 +534,10 @@ header { 1% { display: inline-block; opacity: 0; - transform: translate(-50%, 40%); } 100% { opacity: 1; visibility: visible; - transform: translate(-50%, 20%); } } @@ -550,9 +548,9 @@ header { display: none; background-color: var(--light); padding: 1em; + margin: 1em; border: 1px solid var(--outlinegray); border-radius: 5px; - transform: translate(-50%, 40%); pointer-events: none; transition: opacity 0.2s ease, transform 0.2s ease; user-select: none; @@ -566,7 +564,6 @@ header { &.visible { opacity: 1; visibility: visible; - transform: translate(-50%, 20%); display: inline-block; animation: dropin 0.2s ease; } @@ -590,8 +587,6 @@ header { } } - - #contact_buttons ul { list-style-type: none; diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 0890983b4..e3c6967a3 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -44,6 +44,9 @@ {{partial "katex.html" .}} + + + {{ $popover := resources.Get "js/popover.js" | resources.Fingerprint "md5" | resources.Minify }} From 81af8c459bc9924b8c7137aee9385ed5f5deeb3c Mon Sep 17 00:00:00 2001 From: y1450 <107429941+y1450@users.noreply.github.com> Date: Thu, 14 Jul 2022 00:02:11 +0200 Subject: [PATCH 091/122] fix: remove console log (#159) --- assets/js/clipboard.js | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/js/clipboard.js b/assets/js/clipboard.js index 6389330e4..78979c824 100644 --- a/assets/js/clipboard.js +++ b/assets/js/clipboard.js @@ -33,6 +33,5 @@ const addCopyButtons = () => { // find chroma inside els[i] let chroma = els[i].getElementsByClassName("chroma")[0]; els[i].insertBefore(button, chroma); - console.log(els[i].lastChild) } } From 8b2a82a96a2c7c3f40fd5648c756db3408947fdb Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 13 Jul 2022 22:27:13 -0700 Subject: [PATCH 092/122] fix: change / to use base url --- layouts/partials/contact.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/partials/contact.html b/layouts/partials/contact.html index 7fb991e9d..e52dc4474 100644 --- a/layouts/partials/contact.html +++ b/layouts/partials/contact.html @@ -4,7 +4,7 @@

      Made by {{ $.Site.Data.config.name }} using Quartz, © {{ dateFormat "2006" now }}

        {{ if not .IsHome }} -
      • Home
      • +
      • Home
      • {{end}} {{- range $.Site.Data.config.links -}}
      • {{.link_name}}
      • From 22c8981bb9a97743f02ab5d5feabda7ff5a6afc4 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 13 Jul 2022 23:37:54 -0700 Subject: [PATCH 093/122] feat: css refactor for easy font change --- assets/js/popover.js | 2 +- assets/styles/base.scss | 167 +++++++++++++++---------------- assets/styles/code-title.scss | 2 +- assets/styles/custom.scss | 6 +- assets/styles/syntax.scss | 2 +- content/notes/preview changes.md | 6 +- content/notes/setup.md | 2 +- layouts/partials/head.html | 4 - 8 files changed, 93 insertions(+), 98 deletions(-) diff --git a/assets/js/popover.js b/assets/js/popover.js index 8eb637d6f..6fec7e5e0 100644 --- a/assets/js/popover.js +++ b/assets/js/popover.js @@ -50,7 +50,7 @@ function initPopover(baseURL, useContextualBacklinks, renderLatex) { li.addEventListener("mouseover", () => { // fix tooltip positioning window.FloatingUIDOM.computePosition(li, el, { - middleware: [window.FloatingUIDOM.offset(15), window.FloatingUIDOM.inline(), window.FloatingUIDOM.shift()], + middleware: [window.FloatingUIDOM.offset(10), window.FloatingUIDOM.inline(), window.FloatingUIDOM.shift()], }).then(({ x, y }) => { Object.assign(el.style, { left: `${x}px`, diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 8898ec39b..f618a3ae4 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -1,13 +1,41 @@ +// Replace this with your own font imports! +@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&family=Inter:wght@400;600;700&family=Source+Sans+Pro:wght@400;600&display=swap'); :root { - --lt-colours-light: var(--light) !important; - --lt-colours-lightgray: var(--lightgray) !important; - --lt-colours-dark: var(--secondary) !important; - --lt-colours-secondary: var(--tertiary) !important; - --lt-colours-gray: var(--outlinegray) !important; + --font-body: "Source Sans Pro"; + --font-header: "Inter"; + --font-mono: "Fira Code" +} + +// typography +html { + scroll-behavior: smooth; + &:lang(ar) { + & p, & h1, & h2, & h3, article { + direction: rtl; + text-align: right; + } + } +} + +.singlePage { + padding: 4em 30vw; + @media all and (max-width: 1200px) { + padding: 25px 5vw; + } +} + + +body { + margin: 0; + height: 100vh; + width: 100vw; + max-width: 100%; + box-sizing: border-box; + background-color: var(--light); } h1, h2, h3, h4, h5, h6, ol, ul, thead { - font-family: Inter; + font-family: var(--font-header); color: var(--dark); font-weight: revert; margin: revert; @@ -19,15 +47,15 @@ h1, h2, h3, h4, h5, h6, ol, ul, thead { } .hanchor { - font-family: Inter; + font-family: var(--font-header); margin-left: -1em; opacity: 0.3; transition: opacity 0.3s ease; color: var(--secondary); } -p, ul, text { - font-family: 'Source Sans Pro', sans-serif; +p, ul, text, a, tr, td { + font-family: var(--font-body); color: var(--gray); fill: var(--gray); font-weight: revert; @@ -35,21 +63,26 @@ p, ul, text { padding: revert; } +tbody, li { + line-height: 1.5em; +} + .mainTOC { - background: var(--lightgray); border-radius: 5px; - padding: 0.75em 1em; -} + padding: 0.75em 0; -.mainTOC details summary { - cursor: zoom-in; - font-family: Inter; - color: var(--dark); - font-weight: 700; -} + & details { + & summary { + cursor: zoom-in; + font-family: var(--font-header); + color: var(--dark); + font-weight: 700; + } -.mainTOC details[open] summary { - cursor: zoom-out; + &[open] summary { + cursor: zoom-out; + } + } } #TableOfContents > ol { @@ -74,13 +107,21 @@ p, ul, text { } & > li::marker, & > li > ol > li::marker { - font-family: Source Sans Pro; + font-family: var(--font-body); font-weight: 700; } } table { + border: 1px solid var(--outlinegray); width: 100%; + padding: 1.5em; + border-collapse: collapse; +} + +td, th { + padding: 0.2em 1em; + border: 1px solid var(--outlinegray); } img { @@ -89,7 +130,7 @@ img { margin: 1em 0; } -p>img+em { +p > img + em { display: block; transform: translateY(-1em); } @@ -98,29 +139,11 @@ sup { line-height: 0 } -p, tbody, li { - font-family: Source Sans Pro; - color: var(--gray); - line-height: 1.5em; -} - blockquote { margin-left: 0em; border-left: 3px solid var(--secondary); padding-left: 1em; transition: border-color 0.2s ease; - - &:hover { - border-color: var(--tertiary); - } -} - -table { - padding: 1.5em; -} - -td, th { - padding: 0.1em 0.5em; } .footnotes p { @@ -156,7 +179,6 @@ td, th { .section { & h3 > a { font-weight: 700; - font-family: Inter; margin: 0; } & p { @@ -165,13 +187,16 @@ td, th { } article { + & > h1 { + font-size: 2em; + } + & > .meta { margin: -1.5em 0 1em 0; opacity: 0.7; } & a { - font-family: Source Sans Pro; font-weight: 600; &.internal-link { @@ -233,55 +258,36 @@ sup > a { padding: 0 0.1em 0 0.2em; } +#page-title > a { + font-family: var(--font-header); +} + a { - font-family: Inter, sans-serif; font-size: 1em; font-weight: 700; text-decoration: none; transition: all 0.2s ease; color: var(--secondary); - &:hover { color: var(--tertiary) !important; } } pre { - font-family: 'Fira Code'; + font-family: var(--font-mono); padding: 0.75em; border-radius: 3px; overflow-x: scroll; } code { - font-family: 'Fira Code'; + font-family: var(--font-mono); font-size: 0.85em; padding: 0.15em 0.3em; border-radius: 5px; background: var(--lightgray); } -html { - scroll-behavior: smooth; - - &:lang(ar) { - & p, & h1, & h2, & h3, article { - direction: rtl; - text-align: right; - } - } -} - -body { - margin: 0; - height: 100vh; - width: 100vw; - //overflow-x: hidden; - max-width: 100%; - box-sizing: border-box; - background-color: var(--light); -} - @keyframes fadeIn { 0% {opacity:0;} 100% {opacity:1;} @@ -305,14 +311,6 @@ hr { background-color: var(--dark); } -.singlePage { - padding: 4em 30vw; - - @media all and (max-width: 1200px) { - padding: 25px 5vw; - } -} - .page-end { display: flex; flex-direction: row; @@ -357,10 +355,6 @@ hr { margin-top: 30vh; } -article > h1 { - font-size: 2em; -} - header { display: flex; flex-direction: row; @@ -444,7 +438,7 @@ header { & > input { box-sizing: border-box; padding: 0.5em 1em; - font-family: Inter, sans-serif; + font-family: var(--font-body); color: var(--dark); font-size: 1.1em; border: 1px solid var(--outlinegray); @@ -544,11 +538,11 @@ header { .popover { z-index: 999; position: absolute; - width: 20em; + width: 20rem; display: none; background-color: var(--light); - padding: 1em; - margin: 1em; + padding: 1rem; + margin: 1rem; border: 1px solid var(--outlinegray); border-radius: 5px; pointer-events: none; @@ -570,17 +564,18 @@ header { & > h3 { font-size: 1rem; - margin: 0.25em 0; + margin: 0.25rem 0; } & > .meta { - margin-top: 0.25em; + margin-top: 0.25rem; opacity: 0.5; - font-family: "JetBrains Mono", monospace; + font-family: var(--font-mono); font-size: 0.8rem; } & > p, & > a { + font-size: 1rem; margin: 0; font-weight: 400; user-select: none; diff --git a/assets/styles/code-title.scss b/assets/styles/code-title.scss index 11b088a79..b384743b8 100644 --- a/assets/styles/code-title.scss +++ b/assets/styles/code-title.scss @@ -1,6 +1,6 @@ .code-title { color: var(--primary) ; - font-family: monospace; + font-family: var(--font-mono); width: max-content; overflow-x: auto; display: inline-block; diff --git a/assets/styles/custom.scss b/assets/styles/custom.scss index 54dbacef6..a7a2e7992 100644 --- a/assets/styles/custom.scss +++ b/assets/styles/custom.scss @@ -1,4 +1,5 @@ // Add your own CSS here! + :root { --light: #faf8f8; --dark: #141021; @@ -22,4 +23,7 @@ --gray: #d4d4d4 !important; --lightgray: #292633 !important; --outlinegray: #343434 !important; -} \ No newline at end of file +} + + + diff --git a/assets/styles/syntax.scss b/assets/styles/syntax.scss index 14153c9a0..62a9fe932 100644 --- a/assets/styles/syntax.scss +++ b/assets/styles/syntax.scss @@ -45,7 +45,7 @@ } .chroma code { - font-family: 'Fira Code' !important; + font-family: var(--font-mono) !important; font-size: 0.85em !important; line-height: 2em !important; background: none !important; diff --git a/content/notes/preview changes.md b/content/notes/preview changes.md index d7e2770eb..b79c635bd 100644 --- a/content/notes/preview changes.md +++ b/content/notes/preview changes.md @@ -14,7 +14,7 @@ This step will generate the list of backlinks for Hugo to parse. Ensure you have ```shell # Install and link `hugo-obsidian` locally -$ go install github.com/jackyzha0/hugo-obsidian@latest +go install github.com/jackyzha0/hugo-obsidian@latest ``` If you are running into an error saying that `command not found: hugo-obsidian`, make sure you set your `GOPATH` correctly! This will allow your terminal to correctly recognize hugo-obsidian as an executable. @@ -26,10 +26,10 @@ Hugo is the static site generator that powers Quartz. [Install Hugo with "extend ``` # Navigate to your local Quartz folder -$ cd +cd # Start local server -$ make serve +make serve # View your site in a browser at http://localhost:1313/ ``` diff --git a/content/notes/setup.md b/content/notes/setup.md index 12df750ee..00254159c 100644 --- a/content/notes/setup.md +++ b/content/notes/setup.md @@ -21,7 +21,7 @@ Then, Fork the repository into your own GitHub account. If you don't have an acc After you've made a fork of the repository, you need to download the files locally onto your machine. Ensure you have `git`, then type the following command replacing `YOUR-USERNAME` with your GitHub username. ```shell -$ git clone https://github.com/YOUR-USERNAME/quartz +git clone https://github.com/YOUR-USERNAME/quartz ``` ## Editing diff --git a/layouts/partials/head.html b/layouts/partials/head.html index e3c6967a3..4338c0b97 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -23,10 +23,6 @@ {{ end }} - {{$sass := resources.Match "styles/[!_]*.scss" }} {{$css := slice }} {{range $sass}} From 422b6cc25bec38785e52f304261f7a7f392ec9e4 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 13 Jul 2022 23:51:33 -0700 Subject: [PATCH 094/122] feat: css typography improvements --- assets/styles/base.scss | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index f618a3ae4..b2db108ba 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -38,7 +38,7 @@ h1, h2, h3, h4, h5, h6, ol, ul, thead { font-family: var(--font-header); color: var(--dark); font-weight: revert; - margin: revert; + margin: 2rem 0 0; padding: revert; &:hover > .hanchor { @@ -54,7 +54,7 @@ h1, h2, h3, h4, h5, h6, ol, ul, thead { color: var(--secondary); } -p, ul, text, a, tr, td { +p, ul, text, a, tr, td, li { font-family: var(--font-body); color: var(--gray); fill: var(--gray); @@ -63,7 +63,7 @@ p, ul, text, a, tr, td { padding: revert; } -tbody, li { +tbody, li, p { line-height: 1.5em; } @@ -192,7 +192,7 @@ article { } & > .meta { - margin: -1.5em 0 1em 0; + margin: 0 0 1em 0; opacity: 0.7; } @@ -327,7 +327,8 @@ hr { & > .backlinks-container { & > ul { list-style: none; - padding-left: 0; + padding: 0; + margin: 0; & > li { margin: 0.5em 0; @@ -343,6 +344,7 @@ hr { border-radius: 5px; box-sizing: border-box; min-height: 250px; + margin: 0.5em 0; & > svg { margin-bottom: -5px; @@ -576,7 +578,7 @@ header { & > p, & > a { font-size: 1rem; - margin: 0; + margin: 0.7rem 0; font-weight: 400; user-select: none; } From d7a42a2fd7919ac37ff98be31edc34c3511d255f Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 14 Jul 2022 10:30:07 -0700 Subject: [PATCH 095/122] feat: improve styling for lists, fix anchor offset --- assets/styles/base.scss | 60 +++++++++++++++++++-------------- layouts/_default/taxonomy.html | 6 ++-- layouts/_default/term.html | 2 +- layouts/partials/page-list.html | 19 +++++------ 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index b2db108ba..cec7b9105 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -34,12 +34,12 @@ body { background-color: var(--light); } -h1, h2, h3, h4, h5, h6, ol, ul, thead { +h1, h2, h3, h4, h5, h6, thead { font-family: var(--font-header); color: var(--dark); font-weight: revert; margin: 2rem 0 0; - padding: revert; + padding: 2rem auto 1rem; &:hover > .hanchor { opacity: 1; @@ -48,13 +48,12 @@ h1, h2, h3, h4, h5, h6, ol, ul, thead { .hanchor { font-family: var(--font-header); - margin-left: -1em; - opacity: 0.3; + opacity: 0.2; transition: opacity 0.3s ease; color: var(--secondary); } -p, ul, text, a, tr, td, li { +p, ul, text, a, tr, td, li, ol, ul { font-family: var(--font-body); color: var(--gray); fill: var(--gray); @@ -176,16 +175,6 @@ blockquote { } } -.section { - & h3 > a { - font-weight: 700; - margin: 0; - } - & p { - margin-top: 0; - } -} - article { & > h1 { font-size: 2em; @@ -223,6 +212,7 @@ article { padding-left: 0; & .meta { + margin: 1.5em 0; & > h1 { margin: 0; } @@ -258,8 +248,11 @@ sup > a { padding: 0 0.1em 0 0.2em; } -#page-title > a { - font-family: var(--font-header); +#page-title { + margin: 0; + & > a { + font-family: var(--font-header); + } } a { @@ -357,10 +350,15 @@ hr { margin-top: 30vh; } +.spacer { + flex: 1 1 auto; +} + header { display: flex; flex-direction: row; align-items: center; + margin: 1em 0 2em; & > h1 { font-size: 2em; @@ -372,10 +370,6 @@ header { } } - & > .spacer { - flex: 1 1 auto; - } - #search-icon { background-color: var(--lightgray); border-radius: 4px; @@ -385,7 +379,7 @@ header { cursor: pointer; & > p { display: inline; - padding: 0 0.5em 0 1em; + padding: 0 1.5em 0 2em; } } @@ -501,18 +495,32 @@ header { .section-ul { list-style: none; + margin-top: 2em; padding-left: 0; & > li { - border: 1px solid var(--outlinegray); - border-radius: 5px; - padding: 0 1em; margin-bottom: 1em; + & > .section { + display: flex; + align-items: center; + + & h3 > a { + font-weight: 700; + margin: 0; + } + + & p { + margin: 0; + padding-right: 1em; + flex-basis: 6em; + } + } + & h3 { opacity: 1; font-weight: 700; - margin-bottom: 0em; + margin: 0em; } & .meta { diff --git a/layouts/_default/taxonomy.html b/layouts/_default/taxonomy.html index 8f86b648f..4f0b11754 100644 --- a/layouts/_default/taxonomy.html +++ b/layouts/_default/taxonomy.html @@ -12,11 +12,11 @@
        {{ range .Site.Taxonomies.tags.ByCount }}
        -

        {{ .Page.Title }}

        -

        {{ .Count }} notes with this tag {{if gt .Count 2}}(showing first 2 results){{end}}

        +

        {{ .Page.Title | humanize }}

        +

        {{ .Count }} notes with this tag {{if gt .Count 10}}(showing first 10 results){{end}}

        {{ with ($.Site.GetPage (printf "/tags/%s" .Page.Title)) }} - {{partial "page-list.html" (first 2 .Pages.ByLastmod.Reverse)}} + {{partial "page-list.html" (first 10 .Pages.ByLastmod.Reverse)}} {{ end }} {{ end }}
        diff --git a/layouts/_default/term.html b/layouts/_default/term.html index abddc07b4..dbee1c66d 100644 --- a/layouts/_default/term.html +++ b/layouts/_default/term.html @@ -8,7 +8,7 @@ {{partial "header.html" .}}
        -

        Tag: {{.Title | humanize}}

        +

        Tag: {{ .Title }}

        {{partial "page-list.html" .Paginator.Pages}} {{ template "_internal/pagination.html" . }}
        diff --git a/layouts/partials/page-list.html b/layouts/partials/page-list.html index e51c5ddab..f630f1a78 100644 --- a/layouts/partials/page-list.html +++ b/layouts/partials/page-list.html @@ -2,19 +2,18 @@ {{- range . -}}
      • +

        + {{if ne .Date .Lastmod}}{{ .Lastmod.Format "January 2, 2006" }}{{else}}Unknown{{end}} +

        {{- .Title -}}

        - -

        {{- .Summary -}}{{if .Truncated}}...{{end}}

        -

        - {{ .ReadingTime }} minute read. Last updated {{if ne .Date .Lastmod}}{{ .Lastmod.Format "January 2, 2006" }}{{else}}Unknown{{end}} -

        - +
        +
      • {{- end -}} From e0b6606d500e69cc52715729f075808de90f376b Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 14 Jul 2022 10:38:34 -0700 Subject: [PATCH 096/122] fix: make section-li scss more generic --- assets/styles/base.scss | 47 +++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index cec7b9105..7903f6e2b 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -498,34 +498,35 @@ header { margin-top: 2em; padding-left: 0; - & > li { - margin-bottom: 1em; +} - & > .section { - display: flex; - align-items: center; - - & h3 > a { - font-weight: 700; - margin: 0; - } - - & p { - margin: 0; - padding-right: 1em; - flex-basis: 6em; - } - } +.section-li { + margin-bottom: 1em; - & h3 { - opacity: 1; + & > .section { + display: flex; + align-items: center; + + & h3 > a { font-weight: 700; - margin: 0em; + margin: 0; } + + & p { + margin: 0; + padding-right: 1em; + flex-basis: 6em; + } + } - & .meta { - opacity: 0.6; - } + & h3 { + opacity: 1; + font-weight: 700; + margin: 0em; + } + + & .meta { + opacity: 0.6; } } From 7ccff2cf3d4f7a96be2cf890093798067951fd2e Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 14 Jul 2022 11:49:47 -0700 Subject: [PATCH 097/122] fix: styling on page-list for smaller screens --- assets/styles/base.scss | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 7903f6e2b..db8f30d90 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -169,7 +169,7 @@ blockquote { background-color: transparent !important; } - & a[href$="#"] { + & a[href$="#"], &.active a { opacity: 0.2; } } @@ -506,7 +506,13 @@ header { & > .section { display: flex; align-items: center; - + + @media all and (max-width: 600px) { + & .tags { + display: none; + } + } + & h3 > a { font-weight: 700; margin: 0; From b2555ced61628008e9a1321921376c3f9fb53791 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 14 Jul 2022 12:02:35 -0700 Subject: [PATCH 098/122] feat: add description section to section/term/taxonomies, fix header margin --- assets/styles/base.scss | 1 + layouts/_default/section.html | 3 +++ layouts/_default/taxonomy.html | 3 +++ layouts/_default/term.html | 3 +++ 4 files changed, 10 insertions(+) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index db8f30d90..03561f7fc 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -177,6 +177,7 @@ blockquote { article { & > h1 { + margin-top: 2em; font-size: 2em; } diff --git a/layouts/_default/section.html b/layouts/_default/section.html index 2fc714439..96611c4ce 100644 --- a/layouts/_default/section.html +++ b/layouts/_default/section.html @@ -9,6 +9,9 @@ {{partial "header.html" .}}

        All {{.Title}}

        + {{with .Params.description}} +

        {{.}}

        + {{end}} {{partial "page-list.html" .Paginator.Pages.ByLastmod.Reverse }} {{ template "_internal/pagination.html" .}}
        diff --git a/layouts/_default/taxonomy.html b/layouts/_default/taxonomy.html index 4f0b11754..7e401ae03 100644 --- a/layouts/_default/taxonomy.html +++ b/layouts/_default/taxonomy.html @@ -9,6 +9,9 @@ {{partial "header.html" .}}

        All {{.Title}}

        + {{with .Params.description}} +

        {{.}}

        + {{end}}
        {{ range .Site.Taxonomies.tags.ByCount }}
        diff --git a/layouts/_default/term.html b/layouts/_default/term.html index dbee1c66d..79bd4eb05 100644 --- a/layouts/_default/term.html +++ b/layouts/_default/term.html @@ -9,6 +9,9 @@ {{partial "header.html" .}}

        Tag: {{ .Title }}

        + {{with .Params.description}} +

        {{.}}

        + {{end}} {{partial "page-list.html" .Paginator.Pages}} {{ template "_internal/pagination.html" . }}
        From dff5ae0d4debfdb2de226984e86a987d99d039ad Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 14 Jul 2022 13:09:21 -0700 Subject: [PATCH 099/122] style: improve header anchor styling --- assets/styles/base.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 03561f7fc..f7ad909ef 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -42,15 +42,15 @@ h1, h2, h3, h4, h5, h6, thead { padding: 2rem auto 1rem; &:hover > .hanchor { - opacity: 1; + color: var(--secondary); } } .hanchor { font-family: var(--font-header); - opacity: 0.2; - transition: opacity 0.3s ease; - color: var(--secondary); + opacity: 0.8; + transition: color 0.3s ease; + color: var(--dark); } p, ul, text, a, tr, td, li, ol, ul { From e15e39155de54dc1624bab80eefbccd6a783cd0c Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Fri, 15 Jul 2022 14:26:31 -0700 Subject: [PATCH 100/122] fix: give precedence to date created over last modified if defined (#101) --- content/_index.md | 1 + layouts/_default/single.html | 2 +- layouts/partials/date-fmt.html | 7 +++++++ layouts/partials/page-list.html | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 layouts/partials/date-fmt.html diff --git a/content/_index.md b/content/_index.md index 7d6d3f98a..0a7dfc1a3 100644 --- a/content/_index.md +++ b/content/_index.md @@ -24,3 +24,4 @@ If you prefer browsing the contents of this site through a list instead of a gra - 🚧 [Troubleshooting and FAQ](notes/troubleshooting.md) - 🐛 [Submit an Issue](https://github.com/jackyzha0/quartz/issues) - 👀 [Discord Community](https://discord.gg/cRFFHYye7t) + diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 7c2ab10f5..b4dd6dee1 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -10,7 +10,7 @@
        {{if .Title}}

        {{ .Title }}

        {{end}}

        - Last updated {{if ne .Date .Lastmod}}{{ .Lastmod.Format "January 2, 2006" }}{{else}}Unknown{{end}}. + Last updated {{ partial "date-fmt.html" .}} {{ partial "github.html" . }}

          diff --git a/layouts/partials/date-fmt.html b/layouts/partials/date-fmt.html new file mode 100644 index 000000000..6104226e2 --- /dev/null +++ b/layouts/partials/date-fmt.html @@ -0,0 +1,7 @@ +{{if .Date}} +{{.Date.Format "Jan 2, 2006"}} +{{else if .Lastmod}} +{{.Lastmod.Format "Jan 2, 2006"}} +{{else}} +Unknown +{{end}} diff --git a/layouts/partials/page-list.html b/layouts/partials/page-list.html index f630f1a78..385a0e77c 100644 --- a/layouts/partials/page-list.html +++ b/layouts/partials/page-list.html @@ -3,7 +3,7 @@
        • - {{if ne .Date .Lastmod}}{{ .Lastmod.Format "January 2, 2006" }}{{else}}Unknown{{end}} + {{partial "date-fmt.html" .}}

          {{- .Title -}}

          From 1f3da4b8292a7c2ef7eafe9b3a00ef40eb30edac Mon Sep 17 00:00:00 2001 From: Pranav M Date: Mon, 18 Jul 2022 11:45:36 -0400 Subject: [PATCH 101/122] feat: edit the clipboard button to change border colour on success (#162) Co-authored-by: Jacky Zhao --- assets/js/clipboard.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/assets/js/clipboard.js b/assets/js/clipboard.js index 78979c824..cd928c1a4 100644 --- a/assets/js/clipboard.js +++ b/assets/js/clipboard.js @@ -25,7 +25,10 @@ const addCopyButtons = () => { () => { button.blur(); button.innerHTML = svgCheck; - setTimeout(() => (button.innerHTML = svgCopy), 2000); + setTimeout(() => { + button.innerHTML = svgCopy + button.style.borderColor = "" + }, 2000); }, (error) => (button.innerHTML = "Error") ); From d747b19e6104def4b550d86b2ce6ce923773d8ad Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Tue, 19 Jul 2022 09:03:19 -0700 Subject: [PATCH 102/122] docs: copy edits --- README.md | 4 +++- content/_index.md | 5 ++--- content/notes/showcase.md | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 125514a3f..717103c1a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Quartz -Host your second brain and [digital garden](https://jzhao.xyz/posts/digital-gardening) for free. Quartz features +Host your second brain and [digital garden](https://jzhao.xyz/posts/networked-thought) for free. Quartz features 1. Extremely fast full-text search by pressing `Ctrl` + `k` 2. Customizable and hackable design based on Hugo @@ -8,6 +8,8 @@ Host your second brain and [digital garden](https://jzhao.xyz/posts/digital-gard 4. Built-in CJK + Latex Support 5. Support for both Markdown Links and Wikilinks +Check out some of the [amazing gardens that community members](https://quartz.jzhao.xyz/notes/showcase/) have published with Quartz! + > “[One] who works with the door open gets all kinds of interruptions, but [they] also occasionally gets clues as to what the world is and what might be important.” — Richard Hamming 🔗 Get Started: https://quartz.jzhao.xyz/ diff --git a/content/_index.md b/content/_index.md index 0a7dfc1a3..23c4f1ba7 100644 --- a/content/_index.md +++ b/content/_index.md @@ -10,14 +10,13 @@ Host your second brain and [digital garden](https://jzhao.xyz/posts/networked-th 4. Built-in [[notes/CJK + Latex Support (测试) | CJK + Latex Support]] 5. Support for both Markdown Links and Wikilinks +Check out some of the [amazing gardens that community members](notes/showcase.md) have published with Quartz or read about [why I made Quartz](notes/philosophy.md) to begin with. + ## Get Started > 📚 Step 1: [Setup your own digital garden using Quartz](notes/setup.md) -Not convinced yet? Look at some [community digital gardens](notes/showcase.md) built with Quartz, or read about [why I made Quartz](notes/philosophy.md) to begin with. - Returning user? Figure out how to [[notes/updating|update]] your existing Quartz garden. -### Content Lists If you prefer browsing the contents of this site through a list instead of a graph, you see a list of all [setup-related notes](/tags/setup). ### Troubleshooting diff --git a/content/notes/showcase.md b/content/notes/showcase.md index 5c16a0d39..585bbdae1 100644 --- a/content/notes/showcase.md +++ b/content/notes/showcase.md @@ -5,7 +5,8 @@ title: "Showcase" Want to see what Quartz can do? Here are some cool community gardens :) - [Quartz Documentation (this site!)](https://quartz.jzhao.xyz/) -- [Jacky Zhao's Garden](https://garden.jzhao.xyz/) +- [Jacky Zhao's Garden](https://jzhao.xyz/) +- [Scaling Synthesis - A hypertext research notebook](https://scalingsynthesis.com/) - [AWAGMI Intern Notes](https://notes.awagmi.xyz/) - [Shihyu's PKM](https://shihyuho.github.io/pkm/) - [Chloe's Garden](https://garden.chloeabrasada.online/) From 728d8529ec1a782752abd9254fbc4cae11b8468a Mon Sep 17 00:00:00 2001 From: Emile Bangma Date: Sun, 31 Jul 2022 02:29:26 +0200 Subject: [PATCH 103/122] Support Admonition callouts (#166) (closes #88) --- assets/js/callouts.js | 6 + assets/js/search.js | 1 + assets/styles/_callouts.scss | 374 +++++++++++++++++++++++++++ content/_index.md | 1 + content/notes/callouts.md | 97 +++++++ content/notes/config.md | 3 + data/config.yaml | 1 + layouts/partials/head.html | 13 + layouts/partials/textprocessing.html | 33 +++ 9 files changed, 529 insertions(+) create mode 100644 assets/js/callouts.js create mode 100644 assets/styles/_callouts.scss create mode 100644 content/notes/callouts.md diff --git a/assets/js/callouts.js b/assets/js/callouts.js new file mode 100644 index 000000000..080bbb489 --- /dev/null +++ b/assets/js/callouts.js @@ -0,0 +1,6 @@ +const addCollapsibleCallouts = () => { + const collapsibleCallouts = document.querySelectorAll("blockquote.callout-collapsible"); + collapsibleCallouts.forEach(el => el.addEventListener('click', event => { + event.currentTarget.classList.toggle("callout-collapsed"); + })); +} diff --git a/assets/js/search.js b/assets/js/search.js index 5896061ba..d32d98573 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -45,6 +45,7 @@ const removeMarkdown = ( .replace(/(`{3,})(.*?)\1/gm, "$2") .replace(/`(.+?)`/g, "$1") .replace(/\n{2,}/g, "\n\n") + .replace(/\[![a-zA-Z]+\][-\+]? /g, "") } catch (e) { console.error(e) return markdown diff --git a/assets/styles/_callouts.scss b/assets/styles/_callouts.scss new file mode 100644 index 000000000..712920907 --- /dev/null +++ b/assets/styles/_callouts.scss @@ -0,0 +1,374 @@ +:root { + --callout-summary: #00b0ff; + --callout-summary-accent: #7fd7ff; + --callout-bug: #f50057; + --callout-bug-accent: #ff7aa9; + --callout-danger: #ff1744; + --callout-danger-accent: #ff8aa1; + --callout-example: #7c4dff; + --callout-example-accent: #bda5ff; + --callout-fail: #ff5252; + --callout-fail-accent: #ffa8a8; + --callout-info: #00b8d4; + --callout-info-accent: #69ebff; + --callout-note: #448aff; + --callout-note-accent: #a1c4ff; + --callout-question: #64dd17; + --callout-question-accent: #b0f286; + --callout-quote: #9e9e9e; + --callout-quote-accent: #cecece; + --callout-done: #00c853; + --callout-done-accent: #63ffa4; + --callout-important: #00bfa5; + --callout-important-accent: #5fffe9; + --callout-warning: #ff9100; + --callout-warning-accent: #ffc87f; +} + +[saved-theme=dark] { + --callout-summary: #00b0ff !important; + --callout-summary-accent: #00587f !important; + --callout-bug: #f50057 !important; + --callout-bug-accent: #7a002b !important; + --callout-danger: #ff1744 !important; + --callout-danger-accent: #8b001a !important; + --callout-example: #7c4dff !important; + --callout-example-accent: #2b00a6 !important; + --callout-fail: #ff5252 !important; + --callout-fail-accent: #a80000 !important; + --callout-info: #00b8d4 !important; + --callout-info-accent: #005c6a !important; + --callout-note: #448aff !important; + --callout-note-accent: #003ca1 !important; + --callout-question: #64dd17 !important; + --callout-question-accent: #006429 !important; + --callout-quote: #9e9e9e !important; + --callout-quote-accent: #4f4f4f !important; + --callout-done: #00c853 !important; + --callout-done-accent: #006429 !important; + --callout-important: #00bfa5 !important; + --callout-important-accent: #005f52 !important; + --callout-warning: #ff9100 !important; + --callout-warning-accent: #7f4800 !important; +} + +blockquote.callout-collapsible { + cursor: pointer; +} +blockquote.callout-collapsed { + border-bottom-right-radius: 5px !important; + padding-bottom: 0 !important; +} +blockquote.callout-collapsible::after { + content: '-'; + display: inline-block; + height: 24px; + width: 18px; + margin: 0; + position: absolute; + right: 6px; + top: 0; + font-size: 175%; + font-weight: bolder; + font-family: 'Courier New', Courier, monospace; +} +blockquote.callout-collapsed::after { + content: '+' !important; +} +blockquote.callout-collapsed > *:not(:first-child) { + display: none !important; +} + +blockquote[class*="-callout"] { + margin-right: 0; + border-radius: 5px; + position: relative; + padding-left: 0 !important; + padding-bottom: 0.25em; + color: var(--dark); + background-color: var(--outlinegray); +} +blockquote[class*="-callout"] > p { + border-top-right-radius: 5px; + padding-left: 1em; + padding-right: 1em; + color: var(--dark); + background-color: var(--outlinegray); +} +blockquote[class*="-callout"] > p:first-child::after { + display: inline-block; + height: 24px; + width: 18px; + margin: 3px 0; + position: absolute; + left: 6px; + top: 0; +} +blockquote[class*="-callout"] > p:first-child { + font-size: 125%; + font-weight: bold; + padding-left: 30px; + border-bottom-right-radius: 5px; +} + +blockquote.abstract-callout, +blockquote.summary-callout, +blockquote.tldr-callout { + border-left: 6px solid var(--callout-summary) !important; +} +blockquote.abstract-callout > p:first-child, +blockquote.summary-callout > p:first-child, +blockquote.tldr-callout > p:first-child { + background-color: var(--callout-summary-accent) !important; +} +blockquote.abstract-callout > p:first-child::after, +blockquote.summary-callout > p:first-child::after, +blockquote.tldr-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='book' class='svg-inline--callout-fa fa-book fa-w-14' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='book' class='svg-inline--callout-fa fa-book fa-w-14' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-summary) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.bug-callout { + border-left: 6px solid var(--callout-bug) !important; +} +blockquote.bug-callout > p:first-child { + background-color: var(--callout-bug-accent) !important; +} +blockquote.bug-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='bug' class='svg-inline--callout-fa fa-bug fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M511.988 288.9c-.478 17.43-15.217 31.1-32.653 31.1H424v16c0 21.864-4.882 42.584-13.6 61.145l60.228 60.228c12.496 12.497 12.496 32.758 0 45.255-12.498 12.497-32.759 12.496-45.256 0l-54.736-54.736C345.886 467.965 314.351 480 280 480V236c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v244c-34.351 0-65.886-12.035-90.636-32.108l-54.736 54.736c-12.498 12.497-32.759 12.496-45.256 0-12.496-12.497-12.496-32.758 0-45.255l60.228-60.228C92.882 378.584 88 357.864 88 336v-16H32.666C15.23 320 .491 306.33.013 288.9-.484 270.816 14.028 256 32 256h56v-58.745l-46.628-46.628c-12.496-12.497-12.496-32.758 0-45.255 12.498-12.497 32.758-12.497 45.256 0L141.255 160h229.489l54.627-54.627c12.498-12.497 32.758-12.497 45.256 0 12.496 12.497 12.496 32.758 0 45.255L424 197.255V256h56c17.972 0 32.484 14.816 31.988 32.9zM257 0c-61.856 0-112 50.144-112 112h224C369 50.144 318.856 0 257 0z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='bug' class='svg-inline--callout-fa fa-bug fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M511.988 288.9c-.478 17.43-15.217 31.1-32.653 31.1H424v16c0 21.864-4.882 42.584-13.6 61.145l60.228 60.228c12.496 12.497 12.496 32.758 0 45.255-12.498 12.497-32.759 12.496-45.256 0l-54.736-54.736C345.886 467.965 314.351 480 280 480V236c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v244c-34.351 0-65.886-12.035-90.636-32.108l-54.736 54.736c-12.498 12.497-32.759 12.496-45.256 0-12.496-12.497-12.496-32.758 0-45.255l60.228-60.228C92.882 378.584 88 357.864 88 336v-16H32.666C15.23 320 .491 306.33.013 288.9-.484 270.816 14.028 256 32 256h56v-58.745l-46.628-46.628c-12.496-12.497-12.496-32.758 0-45.255 12.498-12.497 32.758-12.497 45.256 0L141.255 160h229.489l54.627-54.627c12.498-12.497 32.758-12.497 45.256 0 12.496 12.497 12.496 32.758 0 45.255L424 197.255V256h56c17.972 0 32.484 14.816 31.988 32.9zM257 0c-61.856 0-112 50.144-112 112h224C369 50.144 318.856 0 257 0z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-bug) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.danger-callout, +blockquote.error-callout { + border-left: 6px solid var(--callout-danger) !important; +} +blockquote.danger-callout > p:first-child, +blockquote.error-callout > p:first-child { + background-color: var(--callout-danger-accent) !important; +} +blockquote.danger-callout > p:first-child::after, +blockquote.error-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='bolt' class='svg-inline--callout-fa fa-bolt fa-w-10' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='currentColor' d='M296 160H180.6l42.6-129.8C227.2 15 215.7 0 200 0H56C44 0 33.8 8.9 32.2 20.8l-32 240C-1.7 275.2 9.5 288 24 288h118.7L96.6 482.5c-3.6 15.2 8 29.5 23.3 29.5 8.4 0 16.4-4.4 20.8-12l176-304c9.3-15.9-2.2-36-20.7-36z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='bolt' class='svg-inline--callout-fa fa-bolt fa-w-10' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='currentColor' d='M296 160H180.6l42.6-129.8C227.2 15 215.7 0 200 0H56C44 0 33.8 8.9 32.2 20.8l-32 240C-1.7 275.2 9.5 288 24 288h118.7L96.6 482.5c-3.6 15.2 8 29.5 23.3 29.5 8.4 0 16.4-4.4 20.8-12l176-304c9.3-15.9-2.2-36-20.7-36z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-danger) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.example-callout { + border-left: 6px solid var(--callout-example) !important; +} +blockquote.example-callout > p:first-child { + background-color: var(--callout-example-accent) !important; +} +blockquote.example-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='list-ol' class='svg-inline--callout-fa fa-list-ol fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='list-ol' class='svg-inline--callout-fa fa-list-ol fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-example) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.failure-callout, +blockquote.fail-callout, +blockquote.missing-callout { + border-left: 6px solid var(--callout-fail) !important; +} +blockquote.failure-callout > p:first-child, +blockquote.fail-callout > p:first-child, +blockquote.missing-callout > p:first-child { + background-color: var(--callout-fail-accent) !important; +} +blockquote.failure-callout > p:first-child::after, +blockquote.fail-callout > p:first-child::after, +blockquote.missing-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='times-circle' class='svg-inline--callout-fa fa-times-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='times-circle' class='svg-inline--callout-fa fa-times-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-fail) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.info-callout, +blockquote.todo-callout { + border-left: 6px solid var(--callout-info) !important; +} +blockquote.info-callout > p:first-child, +blockquote.todo-callout > p:first-child { + background-color: var(--callout-info-accent) !important; +} +blockquote.info-callout > p:first-child::after, +blockquote.todo-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='info-circle' class='svg-inline--callout-fa fa-info-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='info-circle' class='svg-inline--callout-fa fa-info-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-info) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.note-callout { + border-left: 6px solid var(--callout-note) !important; +} +blockquote.note-callout > p:first-child { + background-color: var(--callout-note-accent) !important; +} +blockquote.note-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='pencil-alt' class='svg-inline--callout-fa fa-pencil-alt fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='pencil-alt' class='svg-inline--callout-fa fa-pencil-alt fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-note) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.question-callout, +blockquote.help-callout, +blockquote.faq-callout { + border-left: 6px solid var(--callout-question) !important; +} +blockquote.question-callout > p:first-child, +blockquote.help-callout > p:first-child, +blockquote.faq-callout > p:first-child { + background-color: var(--callout-question-accent) !important; +} +blockquote.question-callout > p:first-child::after, +blockquote.help-callout > p:first-child::after, +blockquote.faq-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='question-circle' class='svg-inline--callout-fa fa-question-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='question-circle' class='svg-inline--callout-fa fa-question-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-question) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.quote-callout, +blockquote.cite-callout { + border-left: 6px solid var(--callout-quote) !important; +} +blockquote.quote-callout > p:first-child, +blockquote.cite-callout > p:first-child { + background-color: var(--callout-quote-accent) !important; +} +blockquote.quote-callout > p:first-child::after, +blockquote.cite-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='quote-right' class='svg-inline--callout-fa fa-quote-right fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='quote-right' class='svg-inline--callout-fa fa-quote-right fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-quote) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.success-callout, +blockquote.check-callout, +blockquote.done-callout { + border-left: 6px solid var(--callout-done) !important; +} +blockquote.success-callout > p:first-child, +blockquote.check-callout > p:first-child, +blockquote.done-callout > p:first-child { + background-color: var(--callout-done-accent) !important; +} +blockquote.success-callout > p:first-child::after, +blockquote.check-callout > p:first-child::after, +blockquote.done-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='check-circle' class='svg-inline--callout-fa fa-check-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='check-circle' class='svg-inline--callout-fa fa-check-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-done) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.tip-callout, +blockquote.hint-callout, +blockquote.important-callout { + border-left: 6px solid var(--callout-important) !important; +} +blockquote.tip-callout > p:first-child, +blockquote.hint-callout > p:first-child, +blockquote.important-callout > p:first-child { + background-color: var(--callout-important-accent) !important; +} +blockquote.tip-callout > p:first-child::after, +blockquote.hint-callout > p:first-child::after, +blockquote.important-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='fire' class='svg-inline--callout-fa fa-fire fa-w-12' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M216 23.86c0-23.8-30.65-32.77-44.15-13.04C48 191.85 224 200 224 288c0 35.63-29.11 64.46-64.85 63.99-35.17-.45-63.15-29.77-63.15-64.94v-85.51c0-21.7-26.47-32.23-41.43-16.5C27.8 213.16 0 261.33 0 320c0 105.87 86.13 192 192 192s192-86.13 192-192c0-170.29-168-193-168-296.14z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='fire' class='svg-inline--callout-fa fa-fire fa-w-12' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M216 23.86c0-23.8-30.65-32.77-44.15-13.04C48 191.85 224 200 224 288c0 35.63-29.11 64.46-64.85 63.99-35.17-.45-63.15-29.77-63.15-64.94v-85.51c0-21.7-26.47-32.23-41.43-16.5C27.8 213.16 0 261.33 0 320c0 105.87 86.13 192 192 192s192-86.13 192-192c0-170.29-168-193-168-296.14z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-important) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} +blockquote.warning-callout, +blockquote.caution-callout, +blockquote.attention-callout { + border-left: 6px solid var(--callout-warning) !important; +} +blockquote.warning-callout > p:first-child, +blockquote.caution-callout > p:first-child, +blockquote.attention-callout > p:first-child { + background-color: var(--callout-warning-accent) !important; +} +blockquote.warning-callout > p:first-child::after, +blockquote.caution-callout > p:first-child::after, +blockquote.attention-callout > p:first-child::after { + content: ''; + -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='exclamation-triangle' class='svg-inline--callout-fa fa-exclamation-triangle fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z'%3E%3C/path%3E%3C/svg%3E"); + mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='exclamation-triangle' class='svg-inline--callout-fa fa-exclamation-triangle fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z'%3E%3C/path%3E%3C/svg%3E"); + background-color: var(--callout-warning) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; +} diff --git a/content/_index.md b/content/_index.md index 23c4f1ba7..98fe8c9e2 100644 --- a/content/_index.md +++ b/content/_index.md @@ -9,6 +9,7 @@ Host your second brain and [digital garden](https://jzhao.xyz/posts/networked-th 3. Automatically generated backlinks, link previews, and local graph 4. Built-in [[notes/CJK + Latex Support (测试) | CJK + Latex Support]] 5. Support for both Markdown Links and Wikilinks +6. Built-in [[notes/callouts | Callouts Support]] Check out some of the [amazing gardens that community members](notes/showcase.md) have published with Quartz or read about [why I made Quartz](notes/philosophy.md) to begin with. diff --git a/content/notes/callouts.md b/content/notes/callouts.md new file mode 100644 index 000000000..f85cb0a3e --- /dev/null +++ b/content/notes/callouts.md @@ -0,0 +1,97 @@ +--- +title: "Callouts" +--- + +## Callout support + +Supports built-in Callouts. See [documentation on supported types here](https://help.obsidian.md/How+to/Use+callouts#Types). + +## Format: + +``` +> [!example] Example +> +> Text +``` + +Turns to: + +> [!example] Example +> +> Text + +## Collapsible Callouts: + +``` +> [!example]- Starts Collapsed +> +> Text +``` + +Turns to: + +> [!example]- Starts Collapsed +> +> Text + +``` +> [!example]- Starts Opened +> +> Text +``` + +Turns to: + +> [!example]- Starts Opened +> +> Text + +## Showcase: + +> [!example] example +> +> example + +> [!note] note +> +> note + +> [!abstract] abstract, summary, tldr +> +> abstract, summary, tldr + +> [!info] info, todo +> +> info, todo + +> [!tip] tip, hint, important +> +> tip, hint, important + +> [!success] success, check, done +> +> success, check, done + +> [!question] question, help, faq +> +> question, help, faq + +> [!warning] warning, caution, attention +> +> warning, caution, attention + +> [!failure] failure, fail, missing +> +> failure, fail, missing + +> [!danger] danger, error +> +> danger, error + +> [!bug] bug +> +> bug + +> [!quote] quote, cite +> +> quote, cite diff --git a/content/notes/config.md b/content/notes/config.md index e29afda34..7ee27d672 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -31,6 +31,9 @@ enableCodeBlockTitle: true # whether to render copy buttons for code blocks enableCodeBlockCopy: true +# whether to render callouts +enableCallouts: true + # whether to try to process Latex enableLatex: true diff --git a/data/config.yaml b/data/config.yaml index bae38dbaf..1b9021ddf 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -5,6 +5,7 @@ enableLinkPreview: true enableLatex: true enableCodeBlockTitle: true enableCodeBlockCopy: true +enableCallouts: true enableSPA: true enableFooter: true enableContextualBacklinks: true diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 4338c0b97..60db998ed 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -29,6 +29,10 @@ {{$scss := . | resources.ToCSS (dict "outputStyle" "compressed") }} {{$css = $css | append $scss}} {{end}} + {{if $.Site.Data.config.enableCallouts}} + {{$scss := resources.Get "styles/_callouts.scss" | resources.ToCSS (dict "outputStyle" "compressed") }} + {{$css = $css | append $scss}} + {{end}} {{$finalCss := $css | resources.Concat "styles.css" | resources.Fingerprint "md5" | resources.Minify }} @@ -58,6 +62,11 @@ {{ end }} + {{ if $.Site.Data.config.enableCallouts }} + {{ $callouts := resources.Get "js/callouts.js" | resources.Fingerprint "md5" | resources.Minify }} + + {{ end }} + {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint "md5" | resources.Minify | }} {{$contentIndex := resources.Get @@ -97,6 +106,10 @@ addTitleToCodeBlocks(); {{ end }} + {{if $.Site.Data.config.enableCallouts -}} + addCollapsibleCallouts(); + {{ end }} + {{if $.Site.Data.config.enableFooter}} const container = document.getElementById("graph-container") // retry if the graph is not ready diff --git a/layouts/partials/textprocessing.html b/layouts/partials/textprocessing.html index dfb0ff2ef..f6e89f7eb 100644 --- a/layouts/partials/textprocessing.html +++ b/layouts/partials/textprocessing.html @@ -55,4 +55,37 @@ {{/* Add jumpable anchors */}} {{ $content = $content | replaceRE "()(.+)()" `${1}# ${3}${4}` }} +{{/* Callouts */}} +{{if $.Site.Data.config.enableCallouts}} + {{ $content = $content | replaceRE "
          " "
          " }} + {{ $blockquoteclasses := findRE `\[!.+\]` $content }} + {{ $blockquoteclasses1 := findRE "(.|\n)*?
          " $content }} + {{ $blockquotetags := findRE `blockquote class=callout` $content }} + {{ $counter := 0 }} + {{ $counter1 := 0 }} + {{ $finder := index $blockquoteclasses1 $counter }} + {{range $blockquotetags}} + {{ $finder = index $blockquoteclasses1 $counter }} + {{ if (in $finder "[!") }} + {{ $inner := index $blockquoteclasses $counter1 }} + {{ if (in $finder "]-") }} + {{ $inner = $inner | replaceRE `\[!([a-zA-Z]+)\]` `callout-collapsible callout-collapsed ${1}`}} + {{ else if (in $finder "]+") }} + {{ $inner = $inner | replaceRE `\[!([a-zA-Z]+)\]` `callout-collapsible ${1}`}} + {{ else}} + {{ $inner = $inner | replaceRE `\[!([a-zA-Z]+)\]` `${1}` }} + {{ end }} + {{ $inner = printf "blockquote class=\"%s-callout\"" $inner}} + {{ $content = replace $content . $inner 1}} + {{ $counter1 = add $counter1 1 }} + {{ else }} + {{ $inner := print "blockquote" }} + {{ $content = replace $content . $inner 1}} + {{ end }} + {{ $counter = add $counter 1 }} + {{end}} + {{ $content = $content | replaceRE `\[![a-zA-Z]+\][-\+]?` "" }} + {{ $content = $content | replaceRE "blockquote class=callout" "blockquote" }} +{{end}} + {{ $content | safeHTML }} From 234c707a93e1dbe438d0a45f1348cc6c39e2a265 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 30 Jul 2022 18:46:19 -0700 Subject: [PATCH 104/122] docs: improve scss structure and admonition styling, update docs --- assets/styles/_callouts.scss | 76 +++++++++++++++-------------- content/_index.md | 3 +- content/notes/callouts.md | 94 ++++++++++++------------------------ content/notes/updating.md | 2 +- 4 files changed, 72 insertions(+), 103 deletions(-) diff --git a/assets/styles/_callouts.scss b/assets/styles/_callouts.scss index 712920907..d41cdfb13 100644 --- a/assets/styles/_callouts.scss +++ b/assets/styles/_callouts.scss @@ -54,29 +54,24 @@ blockquote.callout-collapsible { cursor: pointer; + + &.callout-collapsible::after { + content: '-'; + right: 6px; + font-weight: bolder; + font-family: 'Courier New', Courier, monospace; + } } + blockquote.callout-collapsed { - border-bottom-right-radius: 5px !important; + & > p { border-bottom-right-radius: 5px !important; } padding-bottom: 0 !important; -} -blockquote.callout-collapsible::after { - content: '-'; - display: inline-block; - height: 24px; - width: 18px; - margin: 0; - position: absolute; - right: 6px; - top: 0; - font-size: 175%; - font-weight: bolder; - font-family: 'Courier New', Courier, monospace; -} -blockquote.callout-collapsed::after { - content: '+' !important; -} -blockquote.callout-collapsed > *:not(:first-child) { - display: none !important; + &::after { + content: '+' !important; + } + & > *:not(:first-child) { + display: none !important; + } } blockquote[class*="-callout"] { @@ -86,29 +81,38 @@ blockquote[class*="-callout"] { padding-left: 0 !important; padding-bottom: 0.25em; color: var(--dark); - background-color: var(--outlinegray); + background-color: var(--lightgray); + + & > p { + border-top-right-radius: 5px; + padding: 0.5em 1em; + margin: 0; + color: var(--gray); + + &:first-child { + font-weight: bold; + color: var(--dark); + padding: 0.4em 30px; + } + } } -blockquote[class*="-callout"] > p { - border-top-right-radius: 5px; - padding-left: 1em; - padding-right: 1em; - color: var(--dark); - background-color: var(--outlinegray); -} -blockquote[class*="-callout"] > p:first-child::after { + +blockquote[class*="-callout"] > p:first-child::after, blockquote.callout-collapsible::after { display: inline-block; - height: 24px; + height: 18px; width: 18px; - margin: 3px 0; position: absolute; - left: 6px; - top: 0; + top: 0.4em; + margin: 0.2em 0.4em; } + blockquote[class*="-callout"] > p:first-child { - font-size: 125%; font-weight: bold; - padding-left: 30px; - border-bottom-right-radius: 5px; + padding: 0.4em 35px; + + &::after { + left: 0; + } } blockquote.abstract-callout, diff --git a/content/_index.md b/content/_index.md index 98fe8c9e2..0278cc5e5 100644 --- a/content/_index.md +++ b/content/_index.md @@ -7,9 +7,8 @@ Host your second brain and [digital garden](https://jzhao.xyz/posts/networked-th 1. Extremely fast full-text search by pressing `Ctrl` + `k` 2. Customizable and hackable design based on Hugo 3. Automatically generated backlinks, link previews, and local graph -4. Built-in [[notes/CJK + Latex Support (测试) | CJK + Latex Support]] +4. Built-in [[notes/CJK + Latex Support (测试) | CJK + Latex Support]] and [[notes/callouts | Admonition-style callouts]] 5. Support for both Markdown Links and Wikilinks -6. Built-in [[notes/callouts | Callouts Support]] Check out some of the [amazing gardens that community members](notes/showcase.md) have published with Quartz or read about [why I made Quartz](notes/philosophy.md) to begin with. diff --git a/content/notes/callouts.md b/content/notes/callouts.md index f85cb0a3e..c71b30584 100644 --- a/content/notes/callouts.md +++ b/content/notes/callouts.md @@ -4,94 +4,60 @@ title: "Callouts" ## Callout support -Supports built-in Callouts. See [documentation on supported types here](https://help.obsidian.md/How+to/Use+callouts#Types). +Quartz supports the same Admonition-callout syntax as Obsidian. -## Format: +This includes +- 12 Distinct callout types (each with several aliases) +- Collapsable callouts -``` -> [!example] Example -> -> Text -``` +See [documentation on supported types and syntax here](https://help.obsidian.md/How+to/Use+callouts#Types). -Turns to: +## Showcase -> [!example] Example +> [!example] Examples > -> Text +> Aliases: example -## Collapsible Callouts: - -``` -> [!example]- Starts Collapsed -> -> Text -``` - -Turns to: - -> [!example]- Starts Collapsed +> [!note] Notes > -> Text +> Aliases: note -``` -> [!example]- Starts Opened -> -> Text -``` - -Turns to: - -> [!example]- Starts Opened +> [!abstract] Summaries > -> Text +> Aliases: abstract, summary, tldr -## Showcase: - -> [!example] example +> [!info] Info > -> example +> Aliases: info, todo -> [!note] note +> [!tip] Hint > -> note +> Aliases: tip, hint, important -> [!abstract] abstract, summary, tldr +> [!success] Success > -> abstract, summary, tldr +> Aliases: success, check, done -> [!info] info, todo +> [!question] Question > -> info, todo +> Aliases: question, help, faq -> [!tip] tip, hint, important +> [!warning] Warning > -> tip, hint, important +> Aliases: warning, caution, attention -> [!success] success, check, done +> [!failure] Failure > -> success, check, done +> Aliases: failure, fail, missing -> [!question] question, help, faq +> [!danger] Error > -> question, help, faq +> Aliases: danger, error -> [!warning] warning, caution, attention +> [!bug] Bug > -> warning, caution, attention +> Aliases: bug -> [!failure] failure, fail, missing +> [!quote] Quote > -> failure, fail, missing - -> [!danger] danger, error -> -> danger, error - -> [!bug] bug -> -> bug - -> [!quote] quote, cite -> -> quote, cite +> Aliases: quote, cite diff --git a/content/notes/updating.md b/content/notes/updating.md index 290d64756..ef4688e99 100644 --- a/content/notes/updating.md +++ b/content/notes/updating.md @@ -18,7 +18,7 @@ make update-force Or, manually checkout the changes yourself. -> ⚠️ **WARNING** ⚠️ +> [!warning] Warning! > > If you customized the files in `data/`, or anything inside `layouts/`, your customization may be overwritten! > Make sure you have a copy of these changes if you don't want to lose them. From 93d039fe7cf14246477844aa1b116585a260003d Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 31 Jul 2022 10:14:36 -0700 Subject: [PATCH 105/122] deps: bump hugo-obsidian version --- .github/workflows/deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 8334ea2ee..27c7a2219 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -14,7 +14,7 @@ jobs: fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Build Link Index - uses: jackyzha0/hugo-obsidian@v2.13 + uses: jackyzha0/hugo-obsidian@v2.14 with: index: true input: content From 14b89105dc10eeb3b9b48abf16eda2b9420c64a0 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 31 Jul 2022 10:54:23 -0700 Subject: [PATCH 106/122] refactor: move search utils to util.js --- assets/js/search.js | 207 +---------------------------------- assets/js/util.js | 207 +++++++++++++++++++++++++++++++++++ layouts/partials/head.html | 9 +- layouts/partials/search.html | 14 ++- 4 files changed, 224 insertions(+), 213 deletions(-) create mode 100644 assets/js/util.js diff --git a/assets/js/search.js b/assets/js/search.js index d32d98573..d296e65d5 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -1,115 +1,4 @@ -// code from https://github.com/danestves/markdown-to-text -const removeMarkdown = ( - markdown, - options = { - listUnicodeChar: false, - stripListLeaders: true, - gfm: true, - useImgAltText: false, - preserveLinks: false, - }, -) => { - let output = markdown || "" - output = output.replace(/^(-\s*?|\*\s*?|_\s*?){3,}\s*$/gm, "") - - try { - if (options.stripListLeaders) { - if (options.listUnicodeChar) - output = output.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, options.listUnicodeChar + " $1") - else output = output.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, "$1") - } - if (options.gfm) { - output = output - .replace(/\n={2,}/g, "\n") - .replace(/~{3}.*\n/g, "") - .replace(/~~/g, "") - .replace(/`{3}.*\n/g, "") - } - if (options.preserveLinks) { - output = output.replace(/\[(.*?)\][\[\(](.*?)[\]\)]/g, "$1 ($2)") - } - output = output - .replace(/<[^>]*>/g, "") - .replace(/^[=\-]{2,}\s*$/g, "") - .replace(/\[\^.+?\](\: .*?$)?/g, "") - .replace(/(#{1,6})\s+(.+)\1?/g, "$2") - .replace(/\s{0,2}\[.*?\]: .*?$/g, "") - .replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, options.useImgAltText ? "$1" : "") - .replace(/\[(.*?)\][\[\(].*?[\]\)]/g, "$1") - .replace(/!?\[\[\S[^\[\]\|]*(?:\|([^\[\]]*))?\S\]\]/g, "$1") - .replace(/^\s{0,3}>\s?/g, "") - .replace(/(^|\n)\s{0,3}>\s?/g, "\n\n") - .replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, "") - .replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, "$2") - .replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, "$2") - .replace(/(`{3,})(.*?)\1/gm, "$2") - .replace(/`(.+?)`/g, "$1") - .replace(/\n{2,}/g, "\n\n") - .replace(/\[![a-zA-Z]+\][-\+]? /g, "") - } catch (e) { - console.error(e) - return markdown - } - return output -} -// ----- - -const highlight = (content, term) => { - const highlightWindow = 20 - - // try to find direct match first - const directMatchIdx = content.indexOf(term) - if (directMatchIdx !== -1) { - const h = highlightWindow / 2 - const before = content.substring(0, directMatchIdx).split(" ").slice(-h) - const after = content - .substring(directMatchIdx + term.length, content.length - 1) - .split(" ") - .slice(0, h) - return ( - (before.length == h ? `...${before.join(" ")}` : before.join(" ")) + - `${term}` + - after.join(" ") - ) - } - - const tokenizedTerm = term.split(/\s+/).filter((t) => t !== "") - const splitText = content.split(/\s+/).filter((t) => t !== "") - const includesCheck = (token) => - tokenizedTerm.some((term) => token.toLowerCase().startsWith(term.toLowerCase())) - - const occurrencesIndices = splitText.map(includesCheck) - - // calculate best index - let bestSum = 0 - let bestIndex = 0 - for (let i = 0; i < Math.max(occurrencesIndices.length - highlightWindow, 0); i++) { - const window = occurrencesIndices.slice(i, i + highlightWindow) - const windowSum = window.reduce((total, cur) => total + cur, 0) - if (windowSum >= bestSum) { - bestSum = windowSum - bestIndex = i - } - } - - const startIndex = Math.max(bestIndex - highlightWindow, 0) - const endIndex = Math.min(startIndex + 2 * highlightWindow, splitText.length) - const mappedText = splitText - .slice(startIndex, endIndex) - .map((token) => { - if (includesCheck(token)) { - return `${token}` - } - return token - }) - .join(" ") - .replaceAll(' ', " ") - return `${startIndex === 0 ? "" : "..."}${mappedText}${ - endIndex === splitText.length ? "" : "..." - }` -} - -;(async function () { +; (async function() { const encoder = (str) => str.toLowerCase().split(/([^a-z]|[^\x00-\x7F])+/) const contentIndex = new FlexSearch.Document({ cache: true, @@ -138,25 +27,6 @@ const highlight = (content, term) => { }) } - const resultToHTML = ({ url, title, content, term }) => { - const text = removeMarkdown(content) - const resultTitle = highlight(title, term) - const resultText = highlight(text, term) - return `` - } - - const redir = (id, term) => { - // SPA navigation - window.Million.navigate( - new URL(`${BASE_URL.replace(/\/$/g, "")}${id}#:~:text=${encodeURIComponent(term)}/`), - ".singlePage", - ) - closeSearch() - } - const formatForDisplay = (id) => ({ id, url: id, @@ -164,16 +34,7 @@ const highlight = (content, term) => { content: content[id].content, }) - const source = document.getElementById("search-bar") - const results = document.getElementById("results-container") - let term - source.addEventListener("keyup", (e) => { - if (e.key === "Enter") { - const anchor = document.getElementsByClassName("result-card")[0] - redir(anchor.id, term) - } - }) - source.addEventListener("input", (e) => { + registerHandlers((e) => { term = e.target.value const searchResults = contentIndex.search(term, [ { @@ -195,68 +56,6 @@ const highlight = (content, term) => { } const allIds = new Set([...getByField("title"), ...getByField("content")]) const finalResults = [...allIds].map(formatForDisplay) - - // display - if (finalResults.length === 0) { - results.innerHTML = `` - } else { - results.innerHTML = finalResults - .map((result) => - resultToHTML({ - ...result, - term, - }), - ) - .join("\n") - const anchors = [...document.getElementsByClassName("result-card")] - anchors.forEach((anchor) => { - anchor.onclick = () => redir(anchor.id, term) - }) - } - }) - - const searchContainer = document.getElementById("search-container") - - function openSearch() { - if (searchContainer.style.display === "none" || searchContainer.style.display === "") { - source.value = "" - results.innerHTML = "" - searchContainer.style.display = "block" - source.focus() - } else { - searchContainer.style.display = "none" - } - } - - function closeSearch() { - searchContainer.style.display = "none" - } - - document.addEventListener("keydown", (event) => { - if (event.key === "k" && (event.ctrlKey || event.metaKey)) { - event.preventDefault() - openSearch() - } - if (event.key === "Escape") { - event.preventDefault() - closeSearch() - } - }) - - const searchButton = document.getElementById("search-icon") - searchButton.addEventListener("click", (evt) => { - openSearch() - }) - searchButton.addEventListener("keydown", (evt) => { - openSearch() - }) - searchContainer.addEventListener("click", (evt) => { - closeSearch() - }) - document.getElementById("search-space").addEventListener("click", (evt) => { - evt.stopPropagation() + displayResults(finalResults) }) })() diff --git a/assets/js/util.js b/assets/js/util.js new file mode 100644 index 000000000..c4652387a --- /dev/null +++ b/assets/js/util.js @@ -0,0 +1,207 @@ +// code from https://github.com/danestves/markdown-to-text +const removeMarkdown = ( + markdown, + options = { + listUnicodeChar: false, + stripListLeaders: true, + gfm: true, + useImgAltText: false, + preserveLinks: false, + }, +) => { + let output = markdown || "" + output = output.replace(/^(-\s*?|\*\s*?|_\s*?){3,}\s*$/gm, "") + + try { + if (options.stripListLeaders) { + if (options.listUnicodeChar) + output = output.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, options.listUnicodeChar + " $1") + else output = output.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, "$1") + } + if (options.gfm) { + output = output + .replace(/\n={2,}/g, "\n") + .replace(/~{3}.*\n/g, "") + .replace(/~~/g, "") + .replace(/`{3}.*\n/g, "") + } + if (options.preserveLinks) { + output = output.replace(/\[(.*?)\][\[\(](.*?)[\]\)]/g, "$1 ($2)") + } + output = output + .replace(/<[^>]*>/g, "") + .replace(/^[=\-]{2,}\s*$/g, "") + .replace(/\[\^.+?\](\: .*?$)?/g, "") + .replace(/(#{1,6})\s+(.+)\1?/g, "$2") + .replace(/\s{0,2}\[.*?\]: .*?$/g, "") + .replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, options.useImgAltText ? "$1" : "") + .replace(/\[(.*?)\][\[\(].*?[\]\)]/g, "$1") + .replace(/!?\[\[\S[^\[\]\|]*(?:\|([^\[\]]*))?\S\]\]/g, "$1") + .replace(/^\s{0,3}>\s?/g, "") + .replace(/(^|\n)\s{0,3}>\s?/g, "\n\n") + .replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, "") + .replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, "$2") + .replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, "$2") + .replace(/(`{3,})(.*?)\1/gm, "$2") + .replace(/`(.+?)`/g, "$1") + .replace(/\n{2,}/g, "\n\n") + .replace(/\[![a-zA-Z]+\][-\+]? /g, "") + } catch (e) { + console.error(e) + return markdown + } + return output +} + +const highlight = (content, term) => { + const highlightWindow = 20 + + // try to find direct match first + const directMatchIdx = content.indexOf(term) + if (directMatchIdx !== -1) { + const h = highlightWindow / 2 + const before = content.substring(0, directMatchIdx).split(" ").slice(-h) + const after = content + .substring(directMatchIdx + term.length, content.length - 1) + .split(" ") + .slice(0, h) + return ( + (before.length == h ? `...${before.join(" ")}` : before.join(" ")) + + `${term}` + + after.join(" ") + ) + } + + const tokenizedTerm = term.split(/\s+/).filter((t) => t !== "") + const splitText = content.split(/\s+/).filter((t) => t !== "") + const includesCheck = (token) => + tokenizedTerm.some((term) => token.toLowerCase().startsWith(term.toLowerCase())) + + const occurrencesIndices = splitText.map(includesCheck) + + // calculate best index + let bestSum = 0 + let bestIndex = 0 + for (let i = 0; i < Math.max(occurrencesIndices.length - highlightWindow, 0); i++) { + const window = occurrencesIndices.slice(i, i + highlightWindow) + const windowSum = window.reduce((total, cur) => total + cur, 0) + if (windowSum >= bestSum) { + bestSum = windowSum + bestIndex = i + } + } + + const startIndex = Math.max(bestIndex - highlightWindow, 0) + const endIndex = Math.min(startIndex + 2 * highlightWindow, splitText.length) + const mappedText = splitText + .slice(startIndex, endIndex) + .map((token) => { + if (includesCheck(token)) { + return `${token}` + } + return token + }) + .join(" ") + .replaceAll(' ', " ") + return `${startIndex === 0 ? "" : "..."}${mappedText}${endIndex === splitText.length ? "" : "..." + }` +} + +// Common utilities for search +const resultToHTML = ({ url, title, content, term }) => { + const text = removeMarkdown(content) + const resultTitle = highlight(title, term) + const resultText = highlight(text, term) + return `` +} + +const redir = (id, term) => { + // SPA navigation + window.Million.navigate( + new URL(`${BASE_URL.replace(/\/$/g, "")}${id}#:~:text=${encodeURIComponent(term)}/`), + ".singlePage", + ) + closeSearch() +} + +function openSearch() { + const source = document.getElementById("search-bar") + const results = document.getElementById("results-container") + const searchContainer = document.getElementById("search-container") + if (searchContainer.style.display === "none" || searchContainer.style.display === "") { + source.value = "" + results.innerHTML = "" + searchContainer.style.display = "block" + source.focus() + } else { + searchContainer.style.display = "none" + } +} + +function closeSearch() { + const searchContainer = document.getElementById("search-container") + searchContainer.style.display = "none" +} + +const registerHandlers = (onInputFn) => { + const source = document.getElementById("search-bar") + const searchContainer = document.getElementById("search-container") + let term + source.addEventListener("keyup", (e) => { + if (e.key === "Enter") { + const anchor = document.getElementsByClassName("result-card")[0] + redir(anchor.id, term) + } + }) + source.addEventListener("input", onInputFn) + document.addEventListener("keydown", (event) => { + if (event.key === "k" && (event.ctrlKey || event.metaKey)) { + event.preventDefault() + openSearch() + } + if (event.key === "Escape") { + event.preventDefault() + closeSearch() + } + }) + + const searchButton = document.getElementById("search-icon") + searchButton.addEventListener("click", (_) => { + openSearch() + }) + searchButton.addEventListener("keydown", (_) => { + openSearch() + }) + searchContainer.addEventListener("click", (_) => { + closeSearch() + }) + document.getElementById("search-space").addEventListener("click", (evt) => { + evt.stopPropagation() + }) +} + +const displayResults = (finalResults) => { + const results = document.getElementById("results-container") + if (finalResults.length === 0) { + results.innerHTML = `` + } else { + results.innerHTML = finalResults + .map((result) => + resultToHTML({ + ...result, + term, + }), + ) + .join("\n") + const anchors = [...document.getElementsByClassName("result-card")] + anchors.forEach((anchor) => { + anchor.onclick = () => redir(anchor.id, term) + }) + } +} diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 60db998ed..acc2efd24 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -40,10 +40,13 @@ - {{ $darkMode := resources.Get "js/darkmode.js" | resources.ExecuteAsTemplate "js/darkmode.js" . | resources.Fingerprint "md5" | resources.Minify }} - + {{$scripts := (slice "js/darkmode.js" "js/util.js")}} + {{range $scripts}} + {{$scriptname := .}} + {{ $s := resources.Get $scriptname | resources.ExecuteAsTemplate $scriptname . | resources.Fingerprint "md5" | resources.Minify }} + + {{end}} {{partial "katex.html" .}} - diff --git a/layouts/partials/search.html b/layouts/partials/search.html index f727184a6..5b0bbb7de 100644 --- a/layouts/partials/search.html +++ b/layouts/partials/search.html @@ -1,10 +1,12 @@
          -
          - -
          -
          +
          + +
          +
          - -{{ $js := resources.Get "js/search.js" | resources.Fingerprint "md5" | resources.Minify }} + +{{ $js := resources.Get "js/search.js" | resources.Fingerprint "md5" | resources.Minify }} From 5ef9aad501f17b57107a35508a093211ecf2dbd8 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 31 Jul 2022 12:16:36 -0700 Subject: [PATCH 107/122] feat: add support for semantic search using operand --- .gitignore | 1 + assets/js/{search.js => full-text-search.js} | 2 +- assets/js/semantic-search.js | 35 ++++++++++++++++++++ assets/js/util.js | 28 +++++++++------- content/notes/config.md | 6 +++- data/config.yaml | 4 ++- layouts/partials/github.html | 2 +- layouts/partials/search.html | 8 ++++- 8 files changed, 69 insertions(+), 17 deletions(-) rename assets/js/{search.js => full-text-search.js} (97%) create mode 100644 assets/js/semantic-search.js diff --git a/.gitignore b/.gitignore index a7ccdb590..182026f9c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ resources content/.obsidian assets/indices/linkIndex.json assets/indices/contentIndex.json +linkmap diff --git a/assets/js/search.js b/assets/js/full-text-search.js similarity index 97% rename from assets/js/search.js rename to assets/js/full-text-search.js index d296e65d5..5f56101b1 100644 --- a/assets/js/search.js +++ b/assets/js/full-text-search.js @@ -56,6 +56,6 @@ } const allIds = new Set([...getByField("title"), ...getByField("content")]) const finalResults = [...allIds].map(formatForDisplay) - displayResults(finalResults) + displayResults(finalResults, true) }) })() diff --git a/assets/js/semantic-search.js b/assets/js/semantic-search.js new file mode 100644 index 000000000..a62d3d593 --- /dev/null +++ b/assets/js/semantic-search.js @@ -0,0 +1,35 @@ +const apiKey = "{{$.Site.Data.config.operandApiKey}}" + +async function searchContents(query) { + const response = await fetch('https://prod.operand.ai/v3/search/objects', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: apiKey, + }, + body: JSON.stringify({ + query, + max: 10 + }), + }); + return (await response.json()); +} + +function debounce(func, timeout = 300) { + let timer; + return (...args) => { + clearTimeout(timer) + timer = setTimeout(() => { func.apply(this, args); }, timeout) + }; +} + +registerHandlers(debounce((e) => { + term = e.target.value + searchContents(term) + .then((res) => res.results.map(entry => ({ + url: entry.object.metadata.url, + content: entry.snippet, + title: entry.object.title + }))) + .then(results => displayResults(results)) +})) diff --git a/assets/js/util.js b/assets/js/util.js index c4652387a..32e1568ec 100644 --- a/assets/js/util.js +++ b/assets/js/util.js @@ -108,13 +108,11 @@ const highlight = (content, term) => { } // Common utilities for search -const resultToHTML = ({ url, title, content, term }) => { - const text = removeMarkdown(content) - const resultTitle = highlight(title, term) - const resultText = highlight(text, term) +const resultToHTML = ({ url, title, content }) => { + const cleaned = removeMarkdown(content) return `` } @@ -183,7 +181,7 @@ const registerHandlers = (onInputFn) => { }) } -const displayResults = (finalResults) => { +const displayResults = (finalResults, extractHighlight = false) => { const results = document.getElementById("results-container") if (finalResults.length === 0) { results.innerHTML = `` } else { results.innerHTML = finalResults - .map((result) => - resultToHTML({ - ...result, - term, - }), + .map((result) => { + if (extractHighlight) { + return resultToHTML({ + url: result.url, + title: highlight(result.title, term), + content: highlight(result.content, term) + }) + } else { + return resultToHTML(result) + } + } ) .join("\n") const anchors = [...document.getElementsByClassName("result-card")] diff --git a/content/notes/config.md b/content/notes/config.md index 7ee27d672..bc509c2b2 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -54,9 +54,13 @@ enableRecentNotes: false # whether to display and 'edit' button next to the last edited field # that links to github -enableGitHubEdit: false +enableGitHubEdit: true GitHubLink: https://github.com/jackyzha0/quartz/tree/hugo/content +# whether to use Operand to power semantic search +enableSemanticSearch: true +operandApiKey: "1e47d93b-1468-45b7-98d5-7f733d5e45e2" + # page description used for SEO description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, diff --git a/data/config.yaml b/data/config.yaml index 1b9021ddf..23bba0f4f 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -10,8 +10,10 @@ enableSPA: true enableFooter: true enableContextualBacklinks: true enableRecentNotes: false -enableGitHubEdit: false +enableGitHubEdit: true GitHubLink: https://github.com/jackyzha0/quartz/tree/hugo/content +enableSemanticSearch: true +operandApiKey: "1e47d93b-1468-45b7-98d5-7f733d5e45e2" description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, Wikilink support, backlinks, local graph, tags, and link previews. diff --git a/layouts/partials/github.html b/layouts/partials/github.html index a7b3d13ec..21adb63e3 100644 --- a/layouts/partials/github.html +++ b/layouts/partials/github.html @@ -1,3 +1,3 @@ {{if $.Site.Data.config.enableGitHubEdit}} -Edit Source +Edit Source {{end}} diff --git a/layouts/partials/search.html b/layouts/partials/search.html index 5b0bbb7de..86c8613ee 100644 --- a/layouts/partials/search.html +++ b/layouts/partials/search.html @@ -6,7 +6,13 @@
          +{{if $.Site.Data.config.enableSemanticSearch}} +{{ $js := resources.Get "js/semantic-search.js" | resources.ExecuteAsTemplate "js/semantic-search.js" . | resources.Fingerprint "md5" | resources.Minify }} + +{{else}} -{{ $js := resources.Get "js/search.js" | resources.Fingerprint "md5" | resources.Minify }} +{{ $js := resources.Get "js/full-text-search.js" | resources.Fingerprint "md5" | resources.Minify }} +{{end}} + From 54a8fd4a563bd3de815aaae2c9d9efd57e65be22 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 31 Jul 2022 12:24:53 -0700 Subject: [PATCH 108/122] deps: bump hugo-obsidian to properly copy linkmap --- .github/workflows/deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 27c7a2219..f4618ae8e 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -14,7 +14,7 @@ jobs: fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Build Link Index - uses: jackyzha0/hugo-obsidian@v2.14 + uses: jackyzha0/hugo-obsidian@v2.15 with: index: true input: content From dd047305afa0618d2a5cd11baec064a1c74ccb90 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 31 Jul 2022 12:33:36 -0700 Subject: [PATCH 109/122] deps: bump hugo-obsidian to fix bug of writing to non-existent directory during build --- .github/workflows/deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index f4618ae8e..8b8c5ae32 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -14,7 +14,7 @@ jobs: fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Build Link Index - uses: jackyzha0/hugo-obsidian@v2.15 + uses: jackyzha0/hugo-obsidian@v2.16 with: index: true input: content From 23380d0519365d09cb629a66fe2ccba1c56e91f2 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 31 Jul 2022 16:55:25 -0700 Subject: [PATCH 110/122] fix: title not being selected properly, bump hugo-obsidian for uri fix --- .github/workflows/deploy.yaml | 2 +- assets/js/semantic-search.js | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 8b8c5ae32..a6a6b5378 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -14,7 +14,7 @@ jobs: fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Build Link Index - uses: jackyzha0/hugo-obsidian@v2.16 + uses: jackyzha0/hugo-obsidian@v2.17 with: index: true input: content diff --git a/assets/js/semantic-search.js b/assets/js/semantic-search.js index a62d3d593..45c51e0b0 100644 --- a/assets/js/semantic-search.js +++ b/assets/js/semantic-search.js @@ -25,11 +25,14 @@ function debounce(func, timeout = 300) { registerHandlers(debounce((e) => { term = e.target.value - searchContents(term) - .then((res) => res.results.map(entry => ({ - url: entry.object.metadata.url, - content: entry.snippet, - title: entry.object.title - }))) - .then(results => displayResults(results)) + if (term !== "") { + searchContents(term) + .then((res) => res.results.map(entry => ({ + url: entry.object.properties.url, + content: entry.snippet, + title: entry.object.metadata.title + }) + )) + .then(results => displayResults(results)) + } })) From b10b23a47bb822bc3eee671d24fd954ec8d74a7d Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 31 Jul 2022 18:02:06 -0700 Subject: [PATCH 111/122] docs: add documentation for Operand Search, remove debounce --- assets/js/semantic-search.js | 12 ++------ content/_index.md | 4 +-- content/notes/config.md | 10 +++---- content/notes/preview changes.md | 4 +-- content/notes/search.md | 50 ++++++++++++++++++++++++++++++++ data/config.yaml | 4 +-- 6 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 content/notes/search.md diff --git a/assets/js/semantic-search.js b/assets/js/semantic-search.js index 45c51e0b0..3cebe5a40 100644 --- a/assets/js/semantic-search.js +++ b/assets/js/semantic-search.js @@ -15,15 +15,7 @@ async function searchContents(query) { return (await response.json()); } -function debounce(func, timeout = 300) { - let timer; - return (...args) => { - clearTimeout(timer) - timer = setTimeout(() => { func.apply(this, args); }, timeout) - }; -} - -registerHandlers(debounce((e) => { +registerHandlers((e) => { term = e.target.value if (term !== "") { searchContents(term) @@ -35,4 +27,4 @@ registerHandlers(debounce((e) => { )) .then(results => displayResults(results)) } -})) +}) diff --git a/content/_index.md b/content/_index.md index 0278cc5e5..b5efe4ec2 100644 --- a/content/_index.md +++ b/content/_index.md @@ -4,8 +4,8 @@ title: 🪴 Quartz 3.2 Host your second brain and [digital garden](https://jzhao.xyz/posts/networked-thought) for free. Quartz features -1. Extremely fast full-text search by pressing `Ctrl` + `k` -2. Customizable and hackable design based on Hugo +1. Extremely fast natural-language [[notes/search|search]] +2. Customizable and hackable design based on [Hugo](https://gohugo.io/) 3. Automatically generated backlinks, link previews, and local graph 4. Built-in [[notes/CJK + Latex Support (测试) | CJK + Latex Support]] and [[notes/callouts | Admonition-style callouts]] 5. Support for both Markdown Links and Wikilinks diff --git a/content/notes/config.md b/content/notes/config.md index bc509c2b2..e1633a006 100644 --- a/content/notes/config.md +++ b/content/notes/config.md @@ -52,14 +52,16 @@ enableContextualBacklinks: true # whether to show a section of recent notes on the home page enableRecentNotes: false -# whether to display and 'edit' button next to the last edited field +# whether to display an 'edit' button next to the last edited field # that links to github enableGitHubEdit: true GitHubLink: https://github.com/jackyzha0/quartz/tree/hugo/content # whether to use Operand to power semantic search -enableSemanticSearch: true -operandApiKey: "1e47d93b-1468-45b7-98d5-7f733d5e45e2" +# IMPORTANT: replace this API key with your own if you plan on using +# Operand search! +enableSemanticSearch: false +operandApiKey: "REPLACE-WITH-YOUR-OPERAND-API-KEY" # page description used for SEO description: @@ -79,7 +81,6 @@ links: ``` ### Code Block Titles - To add code block titles with Quartz: 1. Ensure that code block titles are enabled in Quartz's configuration: @@ -142,7 +143,6 @@ attribute, are relative to the `static/` directory. ### Graph View To customize the Interactive Graph view, you can poke around `data/graphConfig.yaml`. - ```yaml {title="data/graphConfig.yaml"} # if true, a Global Graph will be shown on home page with full width, no backlink. # A different set of Local Graphs will be shown on sub pages. diff --git a/content/notes/preview changes.md b/content/notes/preview changes.md index b79c635bd..937b99bab 100644 --- a/content/notes/preview changes.md +++ b/content/notes/preview changes.md @@ -12,7 +12,7 @@ Note that both of these steps need to be completed. ## Install `hugo-obsidian` This step will generate the list of backlinks for Hugo to parse. Ensure you have [Go](https://golang.org/doc/install) (>= 1.16) installed. -```shell +```bash # Install and link `hugo-obsidian` locally go install github.com/jackyzha0/hugo-obsidian@latest ``` @@ -24,7 +24,7 @@ Afterwards, start the Hugo server as shown above and your local backlinks and in ## Installing Hugo Hugo is the static site generator that powers Quartz. [Install Hugo with "extended" Sass/SCSS version](https://gohugo.io/getting-started/installing/) first. Then, -``` +```bash # Navigate to your local Quartz folder cd diff --git a/content/notes/search.md b/content/notes/search.md new file mode 100644 index 000000000..b6a13176e --- /dev/null +++ b/content/notes/search.md @@ -0,0 +1,50 @@ +--- +title: "Search" +--- + +Quartz supports two modes of searching through content. + +## Full-text +Full-text search is the default in Quartz. It produces results that *exactly* match the search query. This is easier to setup but usually produces lower quality matches. + +```yaml {title="data/config.yaml"} +# the default option +enableSemanticSearch: false +``` + +## Natural Language +Natural language search is powered by [Operand](https://operand.ai/). It understands language like a person does and finds results that best match user intent. In this sense, it is closer to how Google Search works. + +Natural language search tends to produce higher quality results than full-text search. + +Here's how to set it up. + +1. Create an Operand Account on [their website](https://operand.ai/). +2. Go to Dashboard > Settings > Integrations. +3. Follow the steps to setup the GitHub integration. Operand needs access to GitHub in order to index your digital garden properly! +4. Head over to Dashboard > Objects and press `(Cmd + K)` to open the omnibar and select 'Create Collection'. + 1. Set the 'Collection Label' to something that will help you remember it. + 2. You can leave the 'Parent Collection' field empty. +5. Click into your newly made Collection. + 1. Press the 'share' button that looks like three dots connected by lines. + 2. Set the 'Interface Type' to `object-search` and click 'Create'. + 3. This will bring you to a new page with a search bar. Ignore this for now. +6. Go back to Dashboard > Settings > API Keys and find your Quartz-specific Operand API key under 'Other keys'. + 1. Copy the key (which looks something like `0e733a7f-9b9c-48c6-9691-b54fa1c8b910`). + 2. Open `data/config.yaml`. Set `enableSemanticSearch` to `true` and `operandApiKey` to your copied key. + +```yaml {title="data/config.yaml"} +# the default option +enableSemanticSearch: true +operandApiKey: "0e733a7f-9b9c-48c6-9691-b54fa1c8b910" +``` +7. Make a commit and push your changes to GitHub. See the [[notes/hosting|hosting]] page if you haven't done this already. + 1. This step is *required* for Operand to be able to properly index your content. + 2. Head over to Dashboard > Objects and select the collection that you made earlier +8. Press `(Cmd + K)` to open the omnibar again and select 'Create GitHub Repo' + 1. Set the 'Repository Label' to `Quartz` + 2. Set the 'Repository Owner' to your GitHub username + 3. Set the 'Repository Ref' to `master` + 4. Set the 'Repository Name' to the name of your repository (usually just `quartz` if you forked the repository without changing the name) + 5. Leave 'Root Path' and 'Root URL' empty +9. Wait for your repository to index and enjoy natural language search in Quartz! \ No newline at end of file diff --git a/data/config.yaml b/data/config.yaml index 23bba0f4f..00c6b741b 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -12,8 +12,8 @@ enableContextualBacklinks: true enableRecentNotes: false enableGitHubEdit: true GitHubLink: https://github.com/jackyzha0/quartz/tree/hugo/content -enableSemanticSearch: true -operandApiKey: "1e47d93b-1468-45b7-98d5-7f733d5e45e2" +enableSemanticSearch: false +operandApiKey: "REPLACE-WITH-YOUR-OPERAND-API-KEY" description: Host your second brain and digital garden for free. Quartz features extremely fast full-text search, Wikilink support, backlinks, local graph, tags, and link previews. From 8fc6b8e28ebd08eb05aea80e602b9f279f660b5b Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 31 Jul 2022 18:21:17 -0700 Subject: [PATCH 112/122] docs: update, re-added debounce --- assets/js/semantic-search.js | 12 ++++++++++-- content/notes/search.md | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/assets/js/semantic-search.js b/assets/js/semantic-search.js index 3cebe5a40..4382817ce 100644 --- a/assets/js/semantic-search.js +++ b/assets/js/semantic-search.js @@ -15,7 +15,15 @@ async function searchContents(query) { return (await response.json()); } -registerHandlers((e) => { +function debounce(func, timeout = 200) { + let timer; + return (...args) => { + clearTimeout(timer) + timer = setTimeout(() => { func.apply(this, args); }, timeout) + }; +} + +registerHandlers(debounce((e) => { term = e.target.value if (term !== "") { searchContents(term) @@ -27,4 +35,4 @@ registerHandlers((e) => { )) .then(results => displayResults(results)) } -}) +})) diff --git a/content/notes/search.md b/content/notes/search.md index b6a13176e..ed170f64d 100644 --- a/content/notes/search.md +++ b/content/notes/search.md @@ -47,4 +47,4 @@ operandApiKey: "0e733a7f-9b9c-48c6-9691-b54fa1c8b910" 3. Set the 'Repository Ref' to `master` 4. Set the 'Repository Name' to the name of your repository (usually just `quartz` if you forked the repository without changing the name) 5. Leave 'Root Path' and 'Root URL' empty -9. Wait for your repository to index and enjoy natural language search in Quartz! \ No newline at end of file +9. Wait for your repository to index and enjoy natural language search in Quartz! Operand refreshes the index every 2h so all you need to do is just push to GitHub to update the contents in the search. \ No newline at end of file From 6dd4c64a4c09eed71718fe67491dda95f286d345 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Mon, 1 Aug 2022 07:59:49 -0700 Subject: [PATCH 113/122] fix: highlights being stripped in non-semantic search mode --- assets/js/util.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/js/util.js b/assets/js/util.js index 32e1568ec..72541d8e5 100644 --- a/assets/js/util.js +++ b/assets/js/util.js @@ -55,16 +55,17 @@ const removeMarkdown = ( const highlight = (content, term) => { const highlightWindow = 20 - // try to find direct match first const directMatchIdx = content.indexOf(term) if (directMatchIdx !== -1) { - const h = highlightWindow / 2 + console.log(directMatchIdx) + const h = highlightWindow const before = content.substring(0, directMatchIdx).split(" ").slice(-h) const after = content - .substring(directMatchIdx + term.length, content.length - 1) + .substring(directMatchIdx + term.length, content.length - 2) .split(" ") .slice(0, h) + console.log(before, after) return ( (before.length == h ? `...${before.join(" ")}` : before.join(" ")) + `${term}` + @@ -109,10 +110,9 @@ const highlight = (content, term) => { // Common utilities for search const resultToHTML = ({ url, title, content }) => { - const cleaned = removeMarkdown(content) return `` } @@ -195,7 +195,7 @@ const displayResults = (finalResults, extractHighlight = false) => { return resultToHTML({ url: result.url, title: highlight(result.title, term), - content: highlight(result.content, term) + content: highlight(removeMarkdown(result.content), term) }) } else { return resultToHTML(result) From 7ffc907907b14722bf691d1cbd5f178c1c0943a6 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 3 Aug 2022 23:46:55 -0700 Subject: [PATCH 114/122] fix: CJK search (closes #163) --- assets/js/full-text-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/full-text-search.js b/assets/js/full-text-search.js index 5f56101b1..a8f7f23c6 100644 --- a/assets/js/full-text-search.js +++ b/assets/js/full-text-search.js @@ -1,5 +1,5 @@ ; (async function() { - const encoder = (str) => str.toLowerCase().split(/([^a-z]|[^\x00-\x7F])+/) + const encoder = (str) => str.toLowerCase().split(/([^a-z]|[^\x00-\x7F])/) const contentIndex = new FlexSearch.Document({ cache: true, charset: "latin:extra", From ff770927fdbb13e07572b3993686686da4493cc9 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 4 Aug 2022 14:50:24 -0700 Subject: [PATCH 115/122] style: _callouts.scss simplification (#169) --- Makefile | 2 +- assets/styles/_callouts.scss | 499 ++++++++++------------------------- 2 files changed, 146 insertions(+), 355 deletions(-) diff --git a/Makefile b/Makefile index 0d29bdacf..5a88927fa 100644 --- a/Makefile +++ b/Makefile @@ -17,4 +17,4 @@ update-force: ## Forcefully pull all changes and don't ask to patch git checkout upstream/hugo -- layouts .github Makefile assets/js assets/styles/base.scss assets/styles/darkmode.scss config.toml data serve: ## Serve Quartz locally - hugo-obsidian -input=content -output=assets/indices -index -root=. && hugo server --enableGitInfo + hugo-obsidian -input=content -output=assets/indices -index -root=. && hugo server --enableGitInfo --minify diff --git a/assets/styles/_callouts.scss b/assets/styles/_callouts.scss index d41cdfb13..00b2f62d7 100644 --- a/assets/styles/_callouts.scss +++ b/assets/styles/_callouts.scss @@ -1,378 +1,169 @@ :root { - --callout-summary: #00b0ff; - --callout-summary-accent: #7fd7ff; - --callout-bug: #f50057; - --callout-bug-accent: #ff7aa9; - --callout-danger: #ff1744; - --callout-danger-accent: #ff8aa1; - --callout-example: #7c4dff; - --callout-example-accent: #bda5ff; - --callout-fail: #ff5252; - --callout-fail-accent: #ffa8a8; - --callout-info: #00b8d4; - --callout-info-accent: #69ebff; - --callout-note: #448aff; - --callout-note-accent: #a1c4ff; - --callout-question: #64dd17; - --callout-question-accent: #b0f286; - --callout-quote: #9e9e9e; - --callout-quote-accent: #cecece; - --callout-done: #00c853; - --callout-done-accent: #63ffa4; - --callout-important: #00bfa5; - --callout-important-accent: #5fffe9; - --callout-warning: #ff9100; - --callout-warning-accent: #ffc87f; + --callout-summary: #00b0ff; + --callout-summary-accent: #7fd7ff; + --callout-bug: #f50057; + --callout-bug-accent: #ff7aa9; + --callout-danger: #ff1744; + --callout-danger-accent: #ff8aa1; + --callout-example: #7c4dff; + --callout-example-accent: #bda5ff; + --callout-fail: #ff5252; + --callout-fail-accent: #ffa8a8; + --callout-info: #00b8d4; + --callout-info-accent: #69ebff; + --callout-note: #448aff; + --callout-note-accent: #a1c4ff; + --callout-question: #64dd17; + --callout-question-accent: #b0f286; + --callout-quote: #9e9e9e; + --callout-quote-accent: #cecece; + --callout-done: #00c853; + --callout-done-accent: #63ffa4; + --callout-important: #00bfa5; + --callout-important-accent: #5fffe9; + --callout-warning: #ff9100; + --callout-warning-accent: #ffc87f; } [saved-theme=dark] { - --callout-summary: #00b0ff !important; - --callout-summary-accent: #00587f !important; - --callout-bug: #f50057 !important; - --callout-bug-accent: #7a002b !important; - --callout-danger: #ff1744 !important; - --callout-danger-accent: #8b001a !important; - --callout-example: #7c4dff !important; - --callout-example-accent: #2b00a6 !important; - --callout-fail: #ff5252 !important; - --callout-fail-accent: #a80000 !important; - --callout-info: #00b8d4 !important; - --callout-info-accent: #005c6a !important; - --callout-note: #448aff !important; - --callout-note-accent: #003ca1 !important; - --callout-question: #64dd17 !important; - --callout-question-accent: #006429 !important; - --callout-quote: #9e9e9e !important; - --callout-quote-accent: #4f4f4f !important; - --callout-done: #00c853 !important; - --callout-done-accent: #006429 !important; - --callout-important: #00bfa5 !important; - --callout-important-accent: #005f52 !important; - --callout-warning: #ff9100 !important; - --callout-warning-accent: #7f4800 !important; + --callout-summary: #00b0ff !important; + --callout-summary-accent: #00587f !important; + --callout-bug: #f50057 !important; + --callout-bug-accent: #7a002b !important; + --callout-danger: #ff1744 !important; + --callout-danger-accent: #8b001a !important; + --callout-example: #7c4dff !important; + --callout-example-accent: #2b00a6 !important; + --callout-fail: #ff5252 !important; + --callout-fail-accent: #a80000 !important; + --callout-info: #00b8d4 !important; + --callout-info-accent: #005c6a !important; + --callout-note: #448aff !important; + --callout-note-accent: #003ca1 !important; + --callout-question: #64dd17 !important; + --callout-question-accent: #006429 !important; + --callout-quote: #9e9e9e !important; + --callout-quote-accent: #4f4f4f !important; + --callout-done: #00c853 !important; + --callout-done-accent: #006429 !important; + --callout-important: #00bfa5 !important; + --callout-important-accent: #005f52 !important; + --callout-warning: #ff9100 !important; + --callout-warning-accent: #7f4800 !important; } blockquote.callout-collapsible { - cursor: pointer; + cursor: pointer; - &.callout-collapsible::after { - content: '-'; - right: 6px; - font-weight: bolder; - font-family: 'Courier New', Courier, monospace; - } + &.callout-collapsible::after { + content: '-'; + right: 6px; + font-weight: bolder; + font-family: Courier New, Courier, monospace; + } } blockquote.callout-collapsed { - & > p { border-bottom-right-radius: 5px !important; } - padding-bottom: 0 !important; - &::after { - content: '+' !important; - } - & > *:not(:first-child) { - display: none !important; - } + & > p { border-bottom-right-radius: 5px !important; } + padding-bottom: 0 !important; + &::after { + content: '+' !important; + } + & > *:not(:first-child) { + display: none !important; + } } blockquote[class*="-callout"] { - margin-right: 0; - border-radius: 5px; - position: relative; - padding-left: 0 !important; - padding-bottom: 0.25em; - color: var(--dark); - background-color: var(--lightgray); - - & > p { - border-top-right-radius: 5px; - padding: 0.5em 1em; - margin: 0; - color: var(--gray); - - &:first-child { - font-weight: bold; - color: var(--dark); - padding: 0.4em 30px; - } + margin-right: 0; + border-radius: 5px; + position: relative; + padding-left: 0 !important; + padding-bottom: 0.25em; + color: var(--dark); + background-color: var(--lightgray); + & > p { + border-top-right-radius: 5px; + padding: 0.5em 1em; + margin: 0; + color: var(--gray); + &:first-child { + font-weight: 600; + color: var(--dark); + padding: 0.4em 30px; } + } } blockquote[class*="-callout"] > p:first-child::after, blockquote.callout-collapsible::after { - display: inline-block; - height: 18px; - width: 18px; - position: absolute; - top: 0.4em; - margin: 0.2em 0.4em; + display: inline-block; + height: 18px; + width: 18px; + position: absolute; + top: 0.4em; + margin: 0.2em 0.4em; } blockquote[class*="-callout"] > p:first-child { - font-weight: bold; - padding: 0.4em 35px; + font-weight: bold; + padding: 0.4em 35px; - &::after { - left: 0; + &::after { + left: 0; + } +} + +$summary: summary, abstract, tldr; +$bug: bug; +$danger: danger, error; +$example: example; +$fail: fail, failure, missing; +$info: info, todo; +$note: note; +$question: question, help, faq; +$quote: quote, cite; +$done: done, success, check; +$important: important, tip, hint; +$warning: warning, caution, attention; +$types: $summary, $bug, $danger, $example, $fail, $info, $note, $question, $quote, $done, $important, $warning; +$svgs: (); +$svgs: map-merge($svgs, ($summary: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='book' class='svg-inline--callout-fa fa-book fa-w-14' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($bug: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='bug' class='svg-inline--callout-fa fa-bug fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M511.988 288.9c-.478 17.43-15.217 31.1-32.653 31.1H424v16c0 21.864-4.882 42.584-13.6 61.145l60.228 60.228c12.496 12.497 12.496 32.758 0 45.255-12.498 12.497-32.759 12.496-45.256 0l-54.736-54.736C345.886 467.965 314.351 480 280 480V236c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v244c-34.351 0-65.886-12.035-90.636-32.108l-54.736 54.736c-12.498 12.497-32.759 12.496-45.256 0-12.496-12.497-12.496-32.758 0-45.255l60.228-60.228C92.882 378.584 88 357.864 88 336v-16H32.666C15.23 320 .491 306.33.013 288.9-.484 270.816 14.028 256 32 256h56v-58.745l-46.628-46.628c-12.496-12.497-12.496-32.758 0-45.255 12.498-12.497 32.758-12.497 45.256 0L141.255 160h229.489l54.627-54.627c12.498-12.497 32.758-12.497 45.256 0 12.496 12.497 12.496 32.758 0 45.255L424 197.255V256h56c17.972 0 32.484 14.816 31.988 32.9zM257 0c-61.856 0-112 50.144-112 112h224C369 50.144 318.856 0 257 0z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($danger: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='bolt' class='svg-inline--callout-fa fa-bolt fa-w-10' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='currentColor' d='M296 160H180.6l42.6-129.8C227.2 15 215.7 0 200 0H56C44 0 33.8 8.9 32.2 20.8l-32 240C-1.7 275.2 9.5 288 24 288h118.7L96.6 482.5c-3.6 15.2 8 29.5 23.3 29.5 8.4 0 16.4-4.4 20.8-12l176-304c9.3-15.9-2.2-36-20.7-36z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($example: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='list-ol' class='svg-inline--callout-fa fa-list-ol fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($fail: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='times-circle' class='svg-inline--callout-fa fa-times-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($info: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='info-circle' class='svg-inline--callout-fa fa-info-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($note: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='pencil-alt' class='svg-inline--callout-fa fa-pencil-alt fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($question: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='question-circle' class='svg-inline--callout-fa fa-question-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($quote: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='quote-right' class='svg-inline--callout-fa fa-quote-right fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($done: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='check-circle' class='svg-inline--callout-fa fa-check-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($important: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='fire' class='svg-inline--callout-fa fa-fire fa-w-12' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M216 23.86c0-23.8-30.65-32.77-44.15-13.04C48 191.85 224 200 224 288c0 35.63-29.11 64.46-64.85 63.99-35.17-.45-63.15-29.77-63.15-64.94v-85.51c0-21.7-26.47-32.23-41.43-16.5C27.8 213.16 0 261.33 0 320c0 105.87 86.13 192 192 192s192-86.13 192-192c0-170.29-168-193-168-296.14z'%3E%3C/path%3E%3C/svg%3E"))); +$svgs: map-merge($svgs, ($warning: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-icon='exclamation-triangle' class='svg-inline--callout-fa fa-exclamation-triangle fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z'%3E%3C/path%3E%3C/svg%3E"))); + +@function getstr($l) { + $v: nth($l, 1); + @return $v; +} + +@each $type in $types { + @each $s in $type { + blockquote.#{$s}-callout { + border-left: 6px solid var(--callout-#{getstr($type)}) !important; + & > p:first-child { + background-color: var(--callout-#{getstr($type)}-accent) !important; + &::after { + content: ''; + -webkit-mask: map-get($svgs, $type); + mask: map-get($svgs, $type); + background-color: var(--callout-#{getstr($type)}) !important; + -webkit-mask-size: contain; + mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; + } + } } -} - -blockquote.abstract-callout, -blockquote.summary-callout, -blockquote.tldr-callout { - border-left: 6px solid var(--callout-summary) !important; -} -blockquote.abstract-callout > p:first-child, -blockquote.summary-callout > p:first-child, -blockquote.tldr-callout > p:first-child { - background-color: var(--callout-summary-accent) !important; -} -blockquote.abstract-callout > p:first-child::after, -blockquote.summary-callout > p:first-child::after, -blockquote.tldr-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='book' class='svg-inline--callout-fa fa-book fa-w-14' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='book' class='svg-inline--callout-fa fa-book fa-w-14' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-summary) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.bug-callout { - border-left: 6px solid var(--callout-bug) !important; -} -blockquote.bug-callout > p:first-child { - background-color: var(--callout-bug-accent) !important; -} -blockquote.bug-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='bug' class='svg-inline--callout-fa fa-bug fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M511.988 288.9c-.478 17.43-15.217 31.1-32.653 31.1H424v16c0 21.864-4.882 42.584-13.6 61.145l60.228 60.228c12.496 12.497 12.496 32.758 0 45.255-12.498 12.497-32.759 12.496-45.256 0l-54.736-54.736C345.886 467.965 314.351 480 280 480V236c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v244c-34.351 0-65.886-12.035-90.636-32.108l-54.736 54.736c-12.498 12.497-32.759 12.496-45.256 0-12.496-12.497-12.496-32.758 0-45.255l60.228-60.228C92.882 378.584 88 357.864 88 336v-16H32.666C15.23 320 .491 306.33.013 288.9-.484 270.816 14.028 256 32 256h56v-58.745l-46.628-46.628c-12.496-12.497-12.496-32.758 0-45.255 12.498-12.497 32.758-12.497 45.256 0L141.255 160h229.489l54.627-54.627c12.498-12.497 32.758-12.497 45.256 0 12.496 12.497 12.496 32.758 0 45.255L424 197.255V256h56c17.972 0 32.484 14.816 31.988 32.9zM257 0c-61.856 0-112 50.144-112 112h224C369 50.144 318.856 0 257 0z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='bug' class='svg-inline--callout-fa fa-bug fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M511.988 288.9c-.478 17.43-15.217 31.1-32.653 31.1H424v16c0 21.864-4.882 42.584-13.6 61.145l60.228 60.228c12.496 12.497 12.496 32.758 0 45.255-12.498 12.497-32.759 12.496-45.256 0l-54.736-54.736C345.886 467.965 314.351 480 280 480V236c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v244c-34.351 0-65.886-12.035-90.636-32.108l-54.736 54.736c-12.498 12.497-32.759 12.496-45.256 0-12.496-12.497-12.496-32.758 0-45.255l60.228-60.228C92.882 378.584 88 357.864 88 336v-16H32.666C15.23 320 .491 306.33.013 288.9-.484 270.816 14.028 256 32 256h56v-58.745l-46.628-46.628c-12.496-12.497-12.496-32.758 0-45.255 12.498-12.497 32.758-12.497 45.256 0L141.255 160h229.489l54.627-54.627c12.498-12.497 32.758-12.497 45.256 0 12.496 12.497 12.496 32.758 0 45.255L424 197.255V256h56c17.972 0 32.484 14.816 31.988 32.9zM257 0c-61.856 0-112 50.144-112 112h224C369 50.144 318.856 0 257 0z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-bug) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.danger-callout, -blockquote.error-callout { - border-left: 6px solid var(--callout-danger) !important; -} -blockquote.danger-callout > p:first-child, -blockquote.error-callout > p:first-child { - background-color: var(--callout-danger-accent) !important; -} -blockquote.danger-callout > p:first-child::after, -blockquote.error-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='bolt' class='svg-inline--callout-fa fa-bolt fa-w-10' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='currentColor' d='M296 160H180.6l42.6-129.8C227.2 15 215.7 0 200 0H56C44 0 33.8 8.9 32.2 20.8l-32 240C-1.7 275.2 9.5 288 24 288h118.7L96.6 482.5c-3.6 15.2 8 29.5 23.3 29.5 8.4 0 16.4-4.4 20.8-12l176-304c9.3-15.9-2.2-36-20.7-36z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='bolt' class='svg-inline--callout-fa fa-bolt fa-w-10' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='currentColor' d='M296 160H180.6l42.6-129.8C227.2 15 215.7 0 200 0H56C44 0 33.8 8.9 32.2 20.8l-32 240C-1.7 275.2 9.5 288 24 288h118.7L96.6 482.5c-3.6 15.2 8 29.5 23.3 29.5 8.4 0 16.4-4.4 20.8-12l176-304c9.3-15.9-2.2-36-20.7-36z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-danger) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.example-callout { - border-left: 6px solid var(--callout-example) !important; -} -blockquote.example-callout > p:first-child { - background-color: var(--callout-example-accent) !important; -} -blockquote.example-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='list-ol' class='svg-inline--callout-fa fa-list-ol fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='list-ol' class='svg-inline--callout-fa fa-list-ol fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-example) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.failure-callout, -blockquote.fail-callout, -blockquote.missing-callout { - border-left: 6px solid var(--callout-fail) !important; -} -blockquote.failure-callout > p:first-child, -blockquote.fail-callout > p:first-child, -blockquote.missing-callout > p:first-child { - background-color: var(--callout-fail-accent) !important; -} -blockquote.failure-callout > p:first-child::after, -blockquote.fail-callout > p:first-child::after, -blockquote.missing-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='times-circle' class='svg-inline--callout-fa fa-times-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='times-circle' class='svg-inline--callout-fa fa-times-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-fail) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.info-callout, -blockquote.todo-callout { - border-left: 6px solid var(--callout-info) !important; -} -blockquote.info-callout > p:first-child, -blockquote.todo-callout > p:first-child { - background-color: var(--callout-info-accent) !important; -} -blockquote.info-callout > p:first-child::after, -blockquote.todo-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='info-circle' class='svg-inline--callout-fa fa-info-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='info-circle' class='svg-inline--callout-fa fa-info-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-info) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.note-callout { - border-left: 6px solid var(--callout-note) !important; -} -blockquote.note-callout > p:first-child { - background-color: var(--callout-note-accent) !important; -} -blockquote.note-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='pencil-alt' class='svg-inline--callout-fa fa-pencil-alt fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='pencil-alt' class='svg-inline--callout-fa fa-pencil-alt fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-note) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.question-callout, -blockquote.help-callout, -blockquote.faq-callout { - border-left: 6px solid var(--callout-question) !important; -} -blockquote.question-callout > p:first-child, -blockquote.help-callout > p:first-child, -blockquote.faq-callout > p:first-child { - background-color: var(--callout-question-accent) !important; -} -blockquote.question-callout > p:first-child::after, -blockquote.help-callout > p:first-child::after, -blockquote.faq-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='question-circle' class='svg-inline--callout-fa fa-question-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='question-circle' class='svg-inline--callout-fa fa-question-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-question) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.quote-callout, -blockquote.cite-callout { - border-left: 6px solid var(--callout-quote) !important; -} -blockquote.quote-callout > p:first-child, -blockquote.cite-callout > p:first-child { - background-color: var(--callout-quote-accent) !important; -} -blockquote.quote-callout > p:first-child::after, -blockquote.cite-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='quote-right' class='svg-inline--callout-fa fa-quote-right fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='quote-right' class='svg-inline--callout-fa fa-quote-right fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-quote) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.success-callout, -blockquote.check-callout, -blockquote.done-callout { - border-left: 6px solid var(--callout-done) !important; -} -blockquote.success-callout > p:first-child, -blockquote.check-callout > p:first-child, -blockquote.done-callout > p:first-child { - background-color: var(--callout-done-accent) !important; -} -blockquote.success-callout > p:first-child::after, -blockquote.check-callout > p:first-child::after, -blockquote.done-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='check-circle' class='svg-inline--callout-fa fa-check-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='check-circle' class='svg-inline--callout-fa fa-check-circle fa-w-16' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-done) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.tip-callout, -blockquote.hint-callout, -blockquote.important-callout { - border-left: 6px solid var(--callout-important) !important; -} -blockquote.tip-callout > p:first-child, -blockquote.hint-callout > p:first-child, -blockquote.important-callout > p:first-child { - background-color: var(--callout-important-accent) !important; -} -blockquote.tip-callout > p:first-child::after, -blockquote.hint-callout > p:first-child::after, -blockquote.important-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='fire' class='svg-inline--callout-fa fa-fire fa-w-12' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M216 23.86c0-23.8-30.65-32.77-44.15-13.04C48 191.85 224 200 224 288c0 35.63-29.11 64.46-64.85 63.99-35.17-.45-63.15-29.77-63.15-64.94v-85.51c0-21.7-26.47-32.23-41.43-16.5C27.8 213.16 0 261.33 0 320c0 105.87 86.13 192 192 192s192-86.13 192-192c0-170.29-168-193-168-296.14z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='fire' class='svg-inline--callout-fa fa-fire fa-w-12' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M216 23.86c0-23.8-30.65-32.77-44.15-13.04C48 191.85 224 200 224 288c0 35.63-29.11 64.46-64.85 63.99-35.17-.45-63.15-29.77-63.15-64.94v-85.51c0-21.7-26.47-32.23-41.43-16.5C27.8 213.16 0 261.33 0 320c0 105.87 86.13 192 192 192s192-86.13 192-192c0-170.29-168-193-168-296.14z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-important) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; -} -blockquote.warning-callout, -blockquote.caution-callout, -blockquote.attention-callout { - border-left: 6px solid var(--callout-warning) !important; -} -blockquote.warning-callout > p:first-child, -blockquote.caution-callout > p:first-child, -blockquote.attention-callout > p:first-child { - background-color: var(--callout-warning-accent) !important; -} -blockquote.warning-callout > p:first-child::after, -blockquote.caution-callout > p:first-child::after, -blockquote.attention-callout > p:first-child::after { - content: ''; - -webkit-mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='exclamation-triangle' class='svg-inline--callout-fa fa-exclamation-triangle fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z'%3E%3C/path%3E%3C/svg%3E"); - mask: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='exclamation-triangle' class='svg-inline--callout-fa fa-exclamation-triangle fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z'%3E%3C/path%3E%3C/svg%3E"); - background-color: var(--callout-warning) !important; - -webkit-mask-size: contain; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-position: center; - mask-position: center; + } } From 3dcc1f1106c1ad81cf6cd0a45f51249d719d694f Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Fri, 5 Aug 2022 11:04:01 -0700 Subject: [PATCH 116/122] feat: better graph scaling (closes #170) --- assets/js/graph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/graph.js b/assets/js/graph.js index 174d4946d..c89877b9a 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -155,7 +155,7 @@ async function drawGraph(baseUrl, isHome, pathColors, graphConfig) { const nodeRadius = (d) => { const numOut = index.links[d.id]?.length || 0 const numIn = index.backlinks[d.id]?.length || 0 - return 3 + (numOut + numIn) / 4 + return 2 + Math.sqrt(numOut + numIn) } // draw individual nodes From 5c76d8dad9d993010c4e57c6de4e90911a3cd11a Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Fri, 5 Aug 2022 11:08:52 -0700 Subject: [PATCH 117/122] fix: make callout detection case-insensitive (closes #171) --- assets/styles/_callouts.scss | 1 + content/notes/callouts.md | 2 +- layouts/partials/textprocessing.html | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/assets/styles/_callouts.scss b/assets/styles/_callouts.scss index 00b2f62d7..04fd2f662 100644 --- a/assets/styles/_callouts.scss +++ b/assets/styles/_callouts.scss @@ -82,6 +82,7 @@ blockquote[class*="-callout"] { padding-bottom: 0.25em; color: var(--dark); background-color: var(--lightgray); + border-left: 6px solid var(--primary) !important; & > p { border-top-right-radius: 5px; padding: 0.5em 1em; diff --git a/content/notes/callouts.md b/content/notes/callouts.md index c71b30584..74b837d61 100644 --- a/content/notes/callouts.md +++ b/content/notes/callouts.md @@ -14,7 +14,7 @@ See [documentation on supported types and syntax here](https://help.obsidian.md/ ## Showcase -> [!example] Examples +> [!EXAMPLE] Examples > > Aliases: example diff --git a/layouts/partials/textprocessing.html b/layouts/partials/textprocessing.html index f6e89f7eb..1cb2583dc 100644 --- a/layouts/partials/textprocessing.html +++ b/layouts/partials/textprocessing.html @@ -75,7 +75,7 @@ {{ else}} {{ $inner = $inner | replaceRE `\[!([a-zA-Z]+)\]` `${1}` }} {{ end }} - {{ $inner = printf "blockquote class=\"%s-callout\"" $inner}} + {{ $inner = printf "blockquote class=\"%s-callout\"" $inner | lower}} {{ $content = replace $content . $inner 1}} {{ $counter1 = add $counter1 1 }} {{ else }} From a78926ede5a951b2ba48e506c93d25060e240c0e Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 11 Aug 2022 11:42:16 -0700 Subject: [PATCH 118/122] feat: link previews to page-list (closes #173) --- assets/js/util.js | 2 -- assets/styles/base.scss | 6 ++++- layouts/partials/footer.html | 4 ++-- layouts/partials/footerIndex.html | 4 ++-- layouts/partials/head.html | 40 ++++++++++++++++--------------- layouts/partials/page-list.html | 2 +- 6 files changed, 31 insertions(+), 27 deletions(-) diff --git a/assets/js/util.js b/assets/js/util.js index 72541d8e5..06db3c1b7 100644 --- a/assets/js/util.js +++ b/assets/js/util.js @@ -58,14 +58,12 @@ const highlight = (content, term) => { // try to find direct match first const directMatchIdx = content.indexOf(term) if (directMatchIdx !== -1) { - console.log(directMatchIdx) const h = highlightWindow const before = content.substring(0, directMatchIdx).split(" ").slice(-h) const after = content .substring(directMatchIdx + term.length, content.length - 2) .split(" ") .slice(0, h) - console.log(before, after) return ( (before.length == h ? `...${before.join(" ")}` : before.join(" ")) + `${term}` + diff --git a/assets/styles/base.scss b/assets/styles/base.scss index f7ad909ef..2b3d90758 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -592,9 +592,13 @@ header { font-size: 0.8rem; } + & > p { + margin: 0; + padding: 0.5rem 0; + } + & > p, & > a { font-size: 1rem; - margin: 0.7rem 0; font-weight: 400; user-select: none; } diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index ddefe75cf..cab44cb9b 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -3,7 +3,7 @@
          {{if $.Site.Data.config.enableFooter}} -
          + {{end}} -{{partial "contact.html" .}} \ No newline at end of file +{{partial "contact.html" .}} diff --git a/layouts/partials/footerIndex.html b/layouts/partials/footerIndex.html index 5f190446a..5b73fa45d 100644 --- a/layouts/partials/footerIndex.html +++ b/layouts/partials/footerIndex.html @@ -1,6 +1,6 @@ {{if $.Site.Data.config.enableFooter}} {{if $.Site.Data.graphConfig.enableGlobalGraph}} -
          + - diff --git a/layouts/_default/taxonomy.html b/layouts/_default/taxonomy.html index 7e401ae03..01ec325ac 100644 --- a/layouts/_default/taxonomy.html +++ b/layouts/_default/taxonomy.html @@ -1,5 +1,5 @@ - + {{ partial "head.html" . }} @@ -8,7 +8,7 @@ {{partial "header.html" .}}
          -

          All {{.Title}}

          +

          {{ i18n "all_posts" . }}

          {{with .Params.description}}

          {{.}}

          {{end}} @@ -16,7 +16,7 @@ {{ range .Site.Taxonomies.tags.ByCount }}

          {{ .Page.Title | humanize }}

          -

          {{ .Count }} notes with this tag {{if gt .Count 10}}(showing first 10 results){{end}}

          +

          {{ .Count }} {{ i18n "notes_count" }} {{if gt .Count 10}}({{ i18n "first_10"}}){{end}}

          {{ with ($.Site.GetPage (printf "/tags/%s" .Page.Title)) }} {{partial "page-list.html" (first 10 .Pages.ByLastmod.Reverse)}} @@ -27,5 +27,4 @@ {{partial "contact.html" .}}
          - diff --git a/layouts/_default/term.html b/layouts/_default/term.html index 79bd4eb05..6bda201bc 100644 --- a/layouts/_default/term.html +++ b/layouts/_default/term.html @@ -1,5 +1,5 @@ - + {{ partial "head.html" . }} @@ -8,7 +8,7 @@ {{partial "header.html" .}}
          -

          Tag: {{ .Title }}

          +

          {{ i18n "tag" }}: {{ .Title }}

          {{with .Params.description}}

          {{.}}

          {{end}} @@ -18,5 +18,4 @@ {{partial "contact.html" .}}
          - diff --git a/layouts/partials/backlinks.html b/layouts/partials/backlinks.html index 23c9091a5..ae6ea1a8e 100644 --- a/layouts/partials/backlinks.html +++ b/layouts/partials/backlinks.html @@ -1,4 +1,4 @@ -

          Backlinks

          +

          {{ i18n "backlinks" }}

          diff --git a/layouts/partials/contact.html b/layouts/partials/contact.html index e52dc4474..3de7d2c68 100644 --- a/layouts/partials/contact.html +++ b/layouts/partials/contact.html @@ -1,12 +1,17 @@ + +{{ $config := cond (eq $.Site.Language.Lang "en") "config" (printf "config.%s" $.Site.Language.Lang) }} +{{ $data := index $.Site.Data $config }}