From ae2f7efde0eb997ab2f7be1cf1513af7f99df599 Mon Sep 17 00:00:00 2001 From: jackyzha0 <j.zhao2k19@gmail.com> Date: Sat, 28 Aug 2021 20:58:14 -0400 Subject: [PATCH 01/10] update showcase --- content/moc/showcase.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/moc/showcase.md b/content/moc/showcase.md index e1cb9a1..20e6a14 100644 --- a/content/moc/showcase.md +++ b/content/moc/showcase.md @@ -11,5 +11,6 @@ Want to see what Quartz can do? Here are some cool community gardens :) - [Shihyu's PKM](https://shihyuho.github.io/pkm/) - [Chloe's Garden](https://garden.chloeabrasada.online/) - [SlRvb's Site](https://slrvb.github.io/Site/) +- [Course notes for Information Technology Advanced Theory](https://a2itnotes.github.io/quartz/) If you want to see your own on here, submit a [Pull Request adding yourself to this file](https://github.com/jackyzha0/quartz/blob/hugo/content/moc/showcase.md)! From 071984a12d1c7887d0ef41b206e01bc5afefb95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20Rodr=C3=ADguez?= <juaoose@users.noreply.github.com> Date: Tue, 31 Aug 2021 16:40:31 -0500 Subject: [PATCH 02/10] fix product typo in external hosting section --- content/notes/hosting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/notes/hosting.md b/content/notes/hosting.md index 7a5973c..c6027bb 100644 --- a/content/notes/hosting.md +++ b/content/notes/hosting.md @@ -80,6 +80,6 @@ Don't want to use GitHub Pages? Hugo builds everything for you! Everything is a Now that your Quartz is live, let's figure out how to make Quartz really *yours*! -π¨ [Customizing Quarts](notes/config.md) +π¨ [Customizing Quartz](notes/config.md) Having problems? Checkout our [FAQ and Troubleshooting guide](notes/troubleshooting.md). \ No newline at end of file From 299533a4f47d2379ddbc209bcd6923a70a81e65d Mon Sep 17 00:00:00 2001 From: Jacky Zhao <j.zhao2k19@gmail.com> Date: Sun, 24 Oct 2021 23:17:00 -0700 Subject: [PATCH 03/10] bump hugo-obsidian version --- .github/workflows/deploy.yaml | 2 +- README.md | 2 +- content/moc/directory.md | 19 ------------------- 3 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 content/moc/directory.md diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 2190194..b36c49c 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - name: Build Link Index - uses: jackyzha0/hugo-obsidian@v2.3 + uses: jackyzha0/hugo-obsidian@v2.4 with: index: true input: content diff --git a/README.md b/README.md index 079e6c1..ec80139 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Quartz Simple second brain and digital garden. -> βHe who works with the door open gets all kinds of interruptions, but he also occasionally gets clues as to what the world is and what might be important.β β Richard Hamming +> β[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/ \ No newline at end of file diff --git a/content/moc/directory.md b/content/moc/directory.md deleted file mode 100644 index b77f2ee..0000000 --- a/content/moc/directory.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "Quartz Documentation" ---- - -## Setup -Welcome to Quartz! Whether you're setting up a website and project for the first time or a seasoned digital gardener, I hope that you'll find something useful about this project. - -Let's get to business and get you started! - -- π [Setup your own digital garden using Quartz](notes/setup.md) -- π [Linking with an Obsidian Vault](notes/obsidian.md) -- π¨ [Customizing and Styling Quartz](notes/config.md) -- π [Hosting Quartz online!](notes/hosting.md) - -Not convinced yet? Look at some [community digital gardens](moc/showcase) built with Quartz! - -## Troubleshooting -- π§ [Troubleshooting and FAQ](notes/troubleshooting.md) -- π [Submit an Issue](https://github.com/jackyzha0/quartz/issues) \ No newline at end of file From 6fd19069deb06988b3d34482a151a79a53b589d0 Mon Sep 17 00:00:00 2001 From: Jacky Zhao <j.zhao2k19@gmail.com> Date: Sun, 24 Oct 2021 23:17:13 -0700 Subject: [PATCH 04/10] search improvements --- layouts/partials/search.html | 363 ++++++++++++++++++----------------- 1 file changed, 187 insertions(+), 176 deletions(-) diff --git a/layouts/partials/search.html b/layouts/partials/search.html index e2285ea..7ee139d 100644 --- a/layouts/partials/search.html +++ b/layouts/partials/search.html @@ -1,208 +1,219 @@ <div id="search-container"> - <div> - <input autocomplete="off" id="search-bar" name="search" type="text" aria-label="Search" placeholder="Search for something..."> + <div id="search-space"> + <input autoComplete="off" id="search-bar" name="search" type="text" aria-label="Search" + placeholder="Search for something..."> <div id="results-container"> </div> </div> </div> <script src="https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@0.7.2/dist/flexsearch.bundle.js"></script> <script> - // 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, ""); + // 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(/\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" - ) - .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; - } - return output; - }; + 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(/\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" + ) + .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; + } + return output; + }; </script> <script> - const contentIndex = new FlexSearch.Worker({ - tokenize: "strict", - charset: "latin:advanced", - context: true, - depth: 3, - cache: 10, - suggest: true, - }) + const contentIndex = new FlexSearch.Worker({ + tokenize: "reverse", + charset: "latin:extra", + suggest: true, + }) - const scrapedContent = {{$.Site.Data.contentIndex}} - for (const [key, value] of Object.entries(scrapedContent)) { - contentIndex.add(key, value.content) - } - - const stopwords = ['i','me','my','myself','we','our','ours','ourselves','you','your','yours','yourself','yourselves','he','him','his','himself','she','her','hers','herself','it','its','itself','they','them','their','theirs','themselves','what','which','who','whom','this','that','these','those','am','is','are','was','were','be','been','being','have','has','had','having','do','does','did','doing','a','an','the','and','but','if','or','because','as','until','while','of','at','by','for','with','about','against','between','into','through','during','before','after','above','below','to','from','up','down','in','out','on','off','over','under','again','further','then','once','here','there','when','where','why','how','all','any','both','each','few','more','most','other','some','such','no','nor','not','only','own','same','so','than','too','very','s','t','can','will','just','don','should','now'] - const highlight = (content, term) => { - const highlightWindow = 15 - const tokenizedTerm = term.split(/\s+/).filter(t => t !== "") - const splitText = content.split(/\s+/).filter(t => t !== "") - const includesCheck = (token) => tokenizedTerm.some(term => token.toLowerCase().includes(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 scrapedContent = {{$.Site.Data.contentIndex}} + for (const [key, value] of Object.entries(scrapedContent)) { + contentIndex.add(key, value.content) } - 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 `<span class="search-highlight">${token}</span>` - } - return token - }) - .join(" ") - .replaceAll('</span> <span class="search-highlight">', " ") - return `${startIndex === 0 ? "" : "..."}${mappedText}${endIndex === splitText.length ? "" : "..."}` - } + const highlight = (content, term) => { + const highlightWindow = 15 + const tokenizedTerm = term.split(/\s+/).filter(t => t !== "") + const splitText = content.split(/\s+/).filter(t => t !== "") + const includesCheck = (token) => tokenizedTerm.some(term => token.toLowerCase().includes(term.toLowerCase())) - const resultToHTML = ({url, title, content, term}) => { - const md = content.split("---")[2] - const text = removeMarkdown(md) - const resultTitle = highlight(title, term) - const resultText = highlight(text, term) - return `<div class="result-card" id="${url}"> + 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 `<span class="search-highlight">${token}</span>` + } + return token + }) + .join(" ") + .replaceAll('</span> <span class="search-highlight">', " ") + return `${startIndex === 0 ? "" : "..."}${mappedText}${endIndex === splitText.length ? "" : "..."}` + } + + const resultToHTML = ({url, title, content, term}) => { + const md = content.split("---")[2] + const text = removeMarkdown(md) + const resultTitle = highlight(title, term) + const resultText = highlight(text, term) + return `<button class="result-card" id="${url}"> <h3>${resultTitle}</h3> <p>${resultText}</p> - </div>` - } + </button>` + } - const source = document.getElementById('search-bar') - const results = document.getElementById("results-container") - source.addEventListener('input', (e) => { - const term = e.target.value - contentIndex.search(term, { - limit: 5, - depth: 3, - suggest: true, - }).then(searchResults => { - const resultIds = [...new Set(searchResults)] - const finalResults = resultIds.map(id => ({ - url: id, - title: scrapedContent[id].title, - content: scrapedContent[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] + window.location.href = `${anchor.id}#:~:text=${encodeURIComponent(term)}` + } + }) + source.addEventListener('input', (e) => { + term = e.target.value + contentIndex.search(term, { + limit: 20, + depth: 3, + suggest: true, + }).then(searchResults => { + const resultIds = [...new Set(searchResults)] + const finalResults = resultIds.map(id => ({ + url: id, + title: scrapedContent[id].title, + content: scrapedContent[id].content + })) - // display - if (finalResults.length === 0) { - results.innerHTML = `<div class="result-card"> + // display + if (finalResults.length === 0) { + results.innerHTML = `<div class="result-card"> <p>No results.</p> </div>` - } else { - results.innerHTML = finalResults - .map(result => resultToHTML({ - ...result, - term, - })) - .join("\n") - const anchors = document.getElementsByClassName("result-card"); - [...anchors].forEach(anchor => { - anchor.onclick = () => { - window.location.href = `${anchor.id}#:~:text=${encodeURIComponent(term)}` - } + } else { + results.innerHTML = finalResults + .map(result => resultToHTML({ + ...result, + term, + })) + .join("\n") + const anchors = document.getElementsByClassName("result-card"); + [...anchors].forEach(anchor => { + anchor.onclick = () => { + window.location.href = `${anchor.id}#:~:text=${encodeURIComponent(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" + 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 === "/") { - event.preventDefault() - openSearch() + function closeSearch() { + searchContainer.style.display = "none" } - if (event.key === "Escape") { - event.preventDefault() - closeSearch() - } - }) - window.addEventListener('DOMContentLoaded', () => { - const searchButton = document.getElementById("search-icon") - searchButton.addEventListener('click', (evt) => { - openSearch() + document.addEventListener('keydown', (event) => { + if (event.key === "/") { + event.preventDefault() + openSearch() + } + if (event.key === "Escape") { + event.preventDefault() + closeSearch() + } }) - searchButton.addEventListener('keydown', (evt) => { - openSearch() + + window.addEventListener('DOMContentLoaded', () => { + 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() + }) }) - }) </script> \ No newline at end of file From c1c061fbea8f6cdc6aec4992d21d2df73dc6ba4e Mon Sep 17 00:00:00 2001 From: Jacky Zhao <j.zhao2k19@gmail.com> Date: Sun, 24 Oct 2021 23:17:20 -0700 Subject: [PATCH 05/10] bump docs --- content/_index.md | 12 ++++++++++-- content/notes/ignore-notes.md | 9 +++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/content/_index.md b/content/_index.md index b665a3d..0994124 100644 --- a/content/_index.md +++ b/content/_index.md @@ -18,6 +18,14 @@ I was really inspired by [Bianca](https://garden.bianca.digital/) and [Joel](htt **The goal of Quartz is to make hosting your own public digital garden free and simple.** You don't even need your own website. Quartz does all of that for you and gives your own little corner of the internet. ## Get Started -The entire Quartz documentation is fully hosted using Quartz! To get started, let's visit the main directory. +The entire Quartz documentation is fully hosted using Quartz! Whether you're setting up a website and project for the first time or a seasoned digital gardener, I hope that you'll find something useful about this project. -π [Directory](moc/directory.md) \ No newline at end of file +Let's get to business and get you started! + +> π [Setup your own digital garden using Quartz](notes/setup.md) + +Not convinced yet? Look at some [community digital gardens](moc/showcase) built with Quartz! + +## Troubleshooting +- π§ [Troubleshooting and FAQ](notes/troubleshooting.md) +- π [Submit an Issue](https://github.com/jackyzha0/quartz/issues) \ No newline at end of file diff --git a/content/notes/ignore-notes.md b/content/notes/ignore-notes.md index 49bf5f3..e031421 100644 --- a/content/notes/ignore-notes.md +++ b/content/notes/ignore-notes.md @@ -15,6 +15,15 @@ ignoreFiles = [ ``` `ignoreFiles` supports the use of Regular Expressions (RegEx) so you can ignore patterns as well (e.g. ignoring all `.png`s by doing `\\.png$`). +To ignore a specific file, you can also add the tag `draft: true` to the frontmatter of a note. + +```markdown +--- +title: Some Private Note +draft: true +--- +... +``` More details in [Hugo's documentation](https://gohugo.io/getting-started/configuration/#ignore-content-and-data-files-when-rendering). From 22a9c0ddfcb38a15d4340f532faca7733349702b Mon Sep 17 00:00:00 2001 From: Jacky Zhao <j.zhao2k19@gmail.com> Date: Sun, 24 Oct 2021 23:31:09 -0700 Subject: [PATCH 06/10] docs updates, add search to main page, fix redir bug --- README.md | 2 +- content/_index.md | 15 +++++++-------- layouts/index.html | 36 ++++++++++++++++++++++++------------ layouts/partials/search.html | 10 ++++++---- 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index ec80139..abcfb68 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Quartz -Simple second brain and digital garden. +Host your own second brain and digital garden for free. > β[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 diff --git a/content/_index.md b/content/_index.md index 0994124..4cfe1be 100644 --- a/content/_index.md +++ b/content/_index.md @@ -1,7 +1,10 @@ -# π± Quartz -## v2.0 +--- +title: πͺ΄ Quartz v2.1 +--- -Simple second brain and [digital garden](https://jzhao.xyz/posts/digital-gardening). +Host your second brain and [digital garden](https://jzhao.xyz/posts/digital-gardening) for free. + +Curious what it can do? You're on it right now! The entire Quartz documentation is fully hosted using Quartz. ## Why Quartz? Hosting a public digital garden isn't easy. There are an overwhelming number of tutorials, resources, and guides for tools like [Notion](https://www.notion.so/), [Roam](https://roamresearch.com/), and [Obsidian](https://obsidian.md/), yet none of them have super easy to use *free* tools to publish that garden to the world. @@ -11,17 +14,13 @@ I've personally found that 2. Having a public digital garden invites open conversations 3. It makes keeping personal notes and knowledge *playful and fun* -> βHe who works with the door open gets all kinds of interruptions, but he also occasionally gets clues as to what the world is and what might be important.β β Richard Hamming +> β[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 I was really inspired by [Bianca](https://garden.bianca.digital/) and [Joel](https://joelhooks.com/digital-garden)'s digital gardens and wanted to try making my own. **The goal of Quartz is to make hosting your own public digital garden free and simple.** You don't even need your own website. Quartz does all of that for you and gives your own little corner of the internet. ## Get Started -The entire Quartz documentation is fully hosted using Quartz! Whether you're setting up a website and project for the first time or a seasoned digital gardener, I hope that you'll find something useful about this project. - -Let's get to business and get you started! - > π [Setup your own digital garden using Quartz](notes/setup.md) Not convinced yet? Look at some [community digital gardens](moc/showcase) built with Quartz! diff --git a/layouts/index.html b/layouts/index.html index fdc03b1..c30cd4f 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -1,16 +1,28 @@ -{{define "head"}} +<!DOCTYPE html> +<html lang="en"> {{ partial "head.html" . }} -{{end}} -{{define "main"}} -<!-- Main Page --> +<body> +{{partial "search.html" .}} <div class="singlePage"> - {{partial "darkmode.html" .}} - {{.Content}} - - <!-- Contact Info --> - <div> - {{partial "footer.html" .}} - </div> + <!-- Begin actual content --> + <header> + {{if .Title}}<h1>{{ .Title }}</h1>{{end}} + <svg tabindex="0" id="search-icon" aria-labelledby="title desc" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.9 19.7"><title id="title">Search Icon</title><desc id="desc">Icon to open search</desc><g class="search-path" fill="none"><path stroke-linecap="square" d="M18.5 18.3l-5.4-5.4"/><circle cx="8" cy="8" r="7"/></g></svg> + <div class="spacer"></div> + {{partial "darkmode.html" .}} + </header> + <article> + {{if $.Site.Data.config.enableToc}} + <aside class="mainTOC"> + <h3>Table of Contents</h3> + {{ .TableOfContents }} + </aside> + {{end}} + {{- .Content -}} + </article> + {{partial "footer.html" .}} </div> -{{end}} +</body> + +</html> diff --git a/layouts/partials/search.html b/layouts/partials/search.html index 7ee139d..78b7765 100644 --- a/layouts/partials/search.html +++ b/layouts/partials/search.html @@ -126,13 +126,17 @@ </button>` } + const redir = (id, term) => { + window.location.href = {{.Site.BaseURL}} + `${id}#:~:text=${encodeURIComponent(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] - window.location.href = `${anchor.id}#:~:text=${encodeURIComponent(term)}` + redir(anchor.id, term) } }) source.addEventListener('input', (e) => { @@ -163,9 +167,7 @@ .join("\n") const anchors = document.getElementsByClassName("result-card"); [...anchors].forEach(anchor => { - anchor.onclick = () => { - window.location.href = `${anchor.id}#:~:text=${encodeURIComponent(term)}` - } + anchor.onclick = () => redir(anchor.id, term) }) } }) From f56642f13cb5bffb8c05b239c6a7b90e1b6453e5 Mon Sep 17 00:00:00 2001 From: Jacky Zhao <j.zhao2k19@gmail.com> Date: Sun, 24 Oct 2021 23:32:55 -0700 Subject: [PATCH 07/10] forgot string lol --- layouts/partials/search.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/partials/search.html b/layouts/partials/search.html index 78b7765..22b50a1 100644 --- a/layouts/partials/search.html +++ b/layouts/partials/search.html @@ -127,7 +127,7 @@ } const redir = (id, term) => { - window.location.href = {{.Site.BaseURL}} + `${id}#:~:text=${encodeURIComponent(term)}` + window.location.href = "{{.Site.BaseURL}}" + `${id}#:~:text=${encodeURIComponent(term)}` } const source = document.getElementById('search-bar') From 1835b97a7a2faf23809bb39d0bec7a2b77b3b81c Mon Sep 17 00:00:00 2001 From: Jacky Zhao <j.zhao2k19@gmail.com> Date: Sun, 24 Oct 2021 23:45:55 -0700 Subject: [PATCH 08/10] better homepage --- content/_index.md | 26 +++++++------------------- content/notes/philosophy.md | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 content/notes/philosophy.md diff --git a/content/_index.md b/content/_index.md index 4cfe1be..d981591 100644 --- a/content/_index.md +++ b/content/_index.md @@ -1,29 +1,17 @@ --- title: πͺ΄ Quartz v2.1 --- - -Host your second brain and [digital garden](https://jzhao.xyz/posts/digital-gardening) for free. - -Curious what it can do? You're on it right now! The entire Quartz documentation is fully hosted using Quartz. - -## Why Quartz? -Hosting a public digital garden isn't easy. There are an overwhelming number of tutorials, resources, and guides for tools like [Notion](https://www.notion.so/), [Roam](https://roamresearch.com/), and [Obsidian](https://obsidian.md/), yet none of them have super easy to use *free* tools to publish that garden to the world. - -I've personally found that -1. It's nice to access notes from anywhere -2. Having a public digital garden invites open conversations -3. It makes keeping personal notes and knowledge *playful and fun* - -> β[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 - -I was really inspired by [Bianca](https://garden.bianca.digital/) and [Joel](https://joelhooks.com/digital-garden)'s digital gardens and wanted to try making my own. - -**The goal of Quartz is to make hosting your own public digital garden free and simple.** You don't even need your own website. Quartz does all of that for you and gives your own little corner of the internet. +Host your second brain and [digital garden](https://jzhao.xyz/posts/digital-gardening) for free. Quartz features +1. Extremely fast full-text search by pressing `/` +2. Beautiful, out-of-the-box website creation and deployment +3. Display for backlinks of each note +4. A customizable graph view +5. Endlessly powerful page and theme customization ## Get Started > π [Setup your own digital garden using Quartz](notes/setup.md) -Not convinced yet? Look at some [community digital gardens](moc/showcase) built with Quartz! +Not convinced yet? Look at some [community digital gardens](moc/showcase) built with Quartz, or read about [why I made Quartz](notes/philosophy.md) to begin with! ## Troubleshooting - π§ [Troubleshooting and FAQ](notes/troubleshooting.md) diff --git a/content/notes/philosophy.md b/content/notes/philosophy.md new file mode 100644 index 0000000..9325415 --- /dev/null +++ b/content/notes/philosophy.md @@ -0,0 +1,17 @@ +--- +title: Quartz Philosophy +--- + +> β[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 + +## Why Quartz? +Hosting a public digital garden isn't easy. There are an overwhelming number of tutorials, resources, and guides for tools like [Notion](https://www.notion.so/), [Roam](https://roamresearch.com/), and [Obsidian](https://obsidian.md/), yet none of them have super easy to use *free* tools to publish that garden to the world. + +I've personally found that +1. It's nice to access notes from anywhere +2. Having a public digital garden invites open conversations +3. It makes keeping personal notes and knowledge *playful and fun* + +I was really inspired by [Bianca](https://garden.bianca.digital/) and [Joel](https://joelhooks.com/digital-garden)'s digital gardens and wanted to try making my own. + +**The goal of Quartz is to make hosting your own public digital garden free and simple.** You don't even need your own website. Quartz does all of that for you and gives your own little corner of the internet. From f7b89db8ee85e54a438db2e2cac3c55e805281c9 Mon Sep 17 00:00:00 2001 From: Jacky Zhao <j.zhao2k19@gmail.com> Date: Mon, 25 Oct 2021 15:00:55 -0700 Subject: [PATCH 09/10] search fix --- layouts/partials/search.html | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/layouts/partials/search.html b/layouts/partials/search.html index 22b50a1..ce6038f 100644 --- a/layouts/partials/search.html +++ b/layouts/partials/search.html @@ -1,7 +1,6 @@ <div id="search-container"> <div id="search-space"> - <input autoComplete="off" id="search-bar" name="search" type="text" aria-label="Search" - placeholder="Search for something..."> + <input autocomplete="off" id="search-bar" name="search" type="text" aria-label="Search" placeholder="Search for something..."> <div id="results-container"> </div> </div> @@ -72,6 +71,7 @@ tokenize: "reverse", charset: "latin:extra", suggest: true, + cache: 10, }) const scrapedContent = {{$.Site.Data.contentIndex}} @@ -80,10 +80,10 @@ } const highlight = (content, term) => { - const highlightWindow = 15 + 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().includes(term.toLowerCase())) + const includesCheck = (token) => tokenizedTerm.some(term => token.toLowerCase().startsWith(term.toLowerCase())) const occurrencesIndices = splitText .map(includesCheck) @@ -116,8 +116,7 @@ } const resultToHTML = ({url, title, content, term}) => { - const md = content.split("---")[2] - const text = removeMarkdown(md) + const text = removeMarkdown(content) const resultTitle = highlight(title, term) const resultText = highlight(text, term) return `<button class="result-card" id="${url}"> @@ -142,8 +141,7 @@ source.addEventListener('input', (e) => { term = e.target.value contentIndex.search(term, { - limit: 20, - depth: 3, + limit: 15, suggest: true, }).then(searchResults => { const resultIds = [...new Set(searchResults)] @@ -175,7 +173,6 @@ const searchContainer = document.getElementById("search-container") - function openSearch() { if (searchContainer.style.display === "none" || searchContainer.style.display === "") { source.value = "" From 03bb3a3bae297b51ffabb0d428f2c555771033f9 Mon Sep 17 00:00:00 2001 From: Jacky Zhao <j.zhao2k19@gmail.com> Date: Mon, 25 Oct 2021 15:06:29 -0700 Subject: [PATCH 10/10] normalize search styling --- assets/base.scss | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/assets/base.scss b/assets/base.scss index a1b5c7b..9811259 100644 --- a/assets/base.scss +++ b/assets/base.scss @@ -280,7 +280,8 @@ header { left: 0; top: 0; width: 100vw; - height: 100vh; + height: 100%; + overflow: scroll; display: none; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); @@ -324,7 +325,18 @@ header { border: 1px solid var(--outlinegray); border-bottom: none; - &:hover { + // normalize button props + font-family: inherit; + font-size: 100%; + line-height: 1.15; + margin: 0; + overflow: visible; + text-transform: none; + text-align: left; + background: var(--light); + outline: none; + + &:hover, &:focus { background: rgba(180, 180, 180, 0.15); }