Merge remote-tracking branch 'origin/v4' into drone-v4
All checks were successful
continuous-integration/drone/push Build is passing

# Conflicts:
#	quartz/components/styles/backlinks.scss
This commit is contained in:
Struchkov Mark 2024-10-11 20:56:51 +03:00
commit 851e05a571
No known key found for this signature in database
GPG Key ID: A3F0AC3F0FA52F3C
20 changed files with 1046 additions and 383 deletions

View File

@ -1,11 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
groups:
production-dependencies:
applies-to: "version-updates"
patterns:
- "*"

View File

@ -0,0 +1,88 @@
name: Docker build & push image
on:
push:
branches: [v4]
tags: ["v*"]
pull_request:
branches: [v4]
paths:
- .github/workflows/docker-build-push.yaml
- quartz/**
workflow_dispatch:
jobs:
build:
if: ${{ github.repository == 'jackyzha0/quartz' }} # Comment this out if you want to publish your own images on a fork!
runs-on: ubuntu-latest
steps:
- name: Set lowercase repository owner environment variable
run: |
echo "OWNER_LOWERCASE=${OWNER,,}" >> ${GITHUB_ENV}
env:
OWNER: "${{ github.repository_owner }}"
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Inject slug/short variables
uses: rlespinasse/github-slug-action@v4.4.1
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
install: true
driver-opts: |
image=moby/buildkit:master
network=host
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@v3.7.0
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
if: github.event_name != 'pull_request'
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata tags and labels on PRs
if: github.event_name == 'pull_request'
id: meta-pr
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ env.OWNER_LOWERCASE }}/quartz
tags: |
type=raw,value=sha-${{ env.GITHUB_SHA_SHORT }}
labels: |
org.opencontainers.image.source="https://github.com/${{ github.repository_owner }}/quartz"
- name: Extract metadata tags and labels for main, release or tag
if: github.event_name != 'pull_request'
id: meta
uses: docker/metadata-action@v5
with:
flavor: |
latest=auto
images: ghcr.io/${{ env.OWNER_LOWERCASE }}/quartz
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}.{{minor}}.{{patch}}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
type=raw,value=sha-${{ env.GITHUB_SHA_SHORT }}
labels: |
maintainer=${{ github.repository_owner }}
org.opencontainers.image.source="https://github.com/${{ github.repository_owner }}/quartz"
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v6
with:
push: ${{ github.event_name != 'pull_request' }}
build-args: |
GIT_SHA=${{ env.GITHUB_SHA }}
DOCKER_LABEL=sha-${{ env.GITHUB_SHA_SHORT }}
tags: ${{ steps.meta.outputs.tags || steps.meta-pr.outputs.tags }}
labels: ${{ steps.meta.outputs.labels || steps.meta-pr.outputs.labels }}
cache-from: type=gha
cache-to: type=gha

View File

@ -21,6 +21,7 @@ const config: QuartzConfig = {
This part of the configuration concerns anything that can affect the whole site. The following is a list breaking down all the things you can configure:
- `pageTitle`: title of the site. This is also used when generating the [[RSS Feed]] for your site.
- `pageTitleSuffix`: a string added to the end of the page title. This only applies to the browser tab title, not the title shown at the top of the page.
- `enableSPA`: whether to enable [[SPA Routing]] on your site.
- `enablePopovers`: whether to enable [[popover previews]] on your site.
- `analytics`: what to use for analytics on your site. Values can be
@ -32,6 +33,7 @@ This part of the configuration concerns anything that can affect the whole site.
- `{ provider: 'posthog', apiKey: '<your-posthog-project-apiKey>', host: '<your-posthog-host>' }`: use [Posthog](https://posthog.com/);
- `{ provider: 'tinylytics', siteId: '<your-site-id>' }`: use [Tinylytics](https://tinylytics.app/);
- `{ provider: 'cabin' }` or `{ provider: 'cabin', host: 'https://cabin.example.com' }` (custom domain): use [Cabin](https://withcabin.com);
- `{provider: 'clarity', projectId: '<your-clarity-id-code' }`: use [Microsoft clarity](https://clarity.microsoft.com/). The project id can be found on top of the overview page.
- `locale`: used for [[i18n]] and date formatting
- `baseUrl`: this is used for sitemaps and RSS feeds that require an absolute URL to know where the canonical 'home' of your site lives. This is normally the deployed URL of your site (e.g. `quartz.jzhao.xyz` for this site). Do not include the protocol (i.e. `https://`) or any leading or trailing slashes.
- This should also include the subpath if you are [[hosting]] on GitHub pages without a custom domain. For example, if my repository is `jackyzha0/quartz`, GitHub pages would deploy to `https://jackyzha0.github.io/quartz` and the `baseUrl` would be `jackyzha0.github.io/quartz`.
@ -101,7 +103,7 @@ transformers: [
]
```
Some plugins are included by default in the[ `quartz.config.ts`](https://github.com/jackyzha0/quartz/blob/v4/quartz.config.ts), but there are more available.
Some plugins are included by default in the [`quartz.config.ts`](https://github.com/jackyzha0/quartz/blob/v4/quartz.config.ts), but there are more available.
You can see a list of all plugins and their configuration options [[tags/plugin|here]].

1043
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -36,40 +36,40 @@
},
"dependencies": {
"@clack/prompts": "^0.7.0",
"@floating-ui/dom": "^1.6.10",
"@floating-ui/dom": "^1.6.11",
"@napi-rs/simple-git": "0.1.19",
"@tweenjs/tween.js": "^25.0.0",
"async-mutex": "^0.5.0",
"chalk": "^5.3.0",
"chokidar": "^3.6.0",
"chokidar": "^4.0.1",
"cli-spinner": "^0.2.10",
"d3": "^7.9.0",
"esbuild-sass-plugin": "^2.16.1",
"esbuild-sass-plugin": "^3.3.1",
"flexsearch": "0.7.43",
"github-slugger": "^2.0.0",
"globby": "^14.0.2",
"gray-matter": "^4.0.3",
"hast-util-to-html": "^9.0.2",
"hast-util-to-html": "^9.0.3",
"hast-util-to-jsx-runtime": "^2.3.0",
"hast-util-to-string": "^3.0.0",
"hast-util-to-string": "^3.0.1",
"is-absolute-url": "^4.0.1",
"js-yaml": "^4.1.0",
"lightningcss": "^1.26.0",
"lightningcss": "^1.27.0",
"mdast-util-find-and-replace": "^3.0.1",
"mdast-util-to-hast": "^13.2.0",
"mdast-util-to-string": "^4.0.0",
"micromorph": "^0.4.5",
"pixi.js": "^8.3.4",
"preact": "^10.24.0",
"pixi.js": "^8.4.1",
"preact": "^10.24.2",
"preact-render-to-string": "^6.5.11",
"pretty-bytes": "^6.1.1",
"pretty-time": "^1.1.0",
"reading-time": "^1.5.0",
"rehype-autolink-headings": "^7.1.0",
"rehype-citation": "^2.1.1",
"rehype-citation": "^2.1.2",
"rehype-katex": "^7.0.1",
"rehype-mathjax": "^6.0.0",
"rehype-pretty-code": "^0.13.2",
"rehype-pretty-code": "^0.14.0",
"rehype-raw": "^7.0.0",
"rehype-slug": "^6.0.0",
"remark": "^15.0.1",
@ -78,12 +78,12 @@
"remark-gfm": "^4.0.0",
"remark-math": "^6.0.0",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.0",
"remark-rehype": "^11.1.1",
"remark-smartypants": "^3.0.2",
"rfdc": "^1.4.1",
"rimraf": "^6.0.1",
"serve-handler": "^6.1.5",
"shiki": "^1.12.1",
"shiki": "^1.22.0",
"source-map-support": "^0.5.21",
"to-vfile": "^8.0.0",
"toml": "^3.0.0",
@ -99,14 +99,14 @@
"@types/d3": "^7.4.3",
"@types/hast": "^3.0.4",
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.5.5",
"@types/node": "^22.7.5",
"@types/pretty-time": "^1.1.5",
"@types/source-map-support": "^0.5.10",
"@types/ws": "^8.5.12",
"@types/yargs": "^17.0.33",
"esbuild": "^0.19.9",
"esbuild": "^0.24.0",
"prettier": "^3.3.3",
"tsx": "^4.19.0",
"typescript": "^5.6.2"
"tsx": "^4.19.1",
"typescript": "^5.6.3"
}
}

View File

@ -9,6 +9,7 @@ import * as Plugin from "./quartz/plugins"
const config: QuartzConfig = {
configuration: {
pageTitle: "🪴 Quartz 4.0",
pageTitleSuffix: "",
enableSPA: true,
enablePopovers: true,
analytics: {

View File

@ -38,9 +38,14 @@ export type Analytics =
provider: "cabin"
host?: string
}
| {
provider: "clarity"
projectId?: string
}
export interface GlobalConfiguration {
pageTitle: string
pageTitleSuffix?: string
/** Whether to enable single-page-app style rendering. this prevents flashes of unstyled content and improves smoothness of Quartz */
enableSPA: boolean
/** Whether to display Wikipedia-style popovers when hovering over links */

View File

@ -6,7 +6,9 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } fro
export default (() => {
const Head: QuartzComponent = ({ cfg, fileData, externalResources }: QuartzComponentProps) => {
const title = fileData.frontmatter?.title ?? i18n(cfg.locale).propertyDefaults.title
const titleSuffix = cfg.pageTitleSuffix ?? ""
const title =
(fileData.frontmatter?.title ?? i18n(cfg.locale).propertyDefaults.title) + titleSuffix
const description =
fileData.description?.trim() ?? i18n(cfg.locale).propertyDefaults.description
const { css, js } = externalResources

View File

@ -25,7 +25,6 @@ function toggleExplorer(this: HTMLElement) {
if (!content) return
content.classList.toggle("collapsed")
content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px"
}
function toggleFolder(evt: MouseEvent) {

View File

@ -23,7 +23,6 @@ function toggleToc(this: HTMLElement) {
const content = this.nextElementSibling as HTMLElement | undefined
if (!content) return
content.classList.toggle("collapsed")
content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px"
}
function setupToc() {
@ -32,7 +31,6 @@ function setupToc() {
const collapsed = toc.classList.contains("collapsed")
const content = toc.nextElementSibling as HTMLElement | undefined
if (!content) return
content.style.maxHeight = collapsed ? "0px" : content.scrollHeight + "px"
toc.addEventListener("click", toggleToc)
window.addCleanup(() => toc.removeEventListener("click", toggleToc))
}

View File

@ -1,10 +1,8 @@
@use "../../styles/variables.scss" as *;
.backlinks {
@media all and not ($desktop) {
overflow-y: auto;
display: initial;
&:after {
flex-direction: column;
/*&:after {
pointer-events: none;
content: "";
width: 100%;
@ -15,36 +13,31 @@
opacity: 1;
transition: opacity 0.3s ease;
background: linear-gradient(transparent 0px, var(--light));
}
}*/
&:has(> .overflow) {
position: unset;
}
& > h3 {
font-size: 1rem;
margin: 0;
}
& > h3 {
font-size: 1rem;
margin: 0;
}
& > ul {
list-style: none;
margin: 0.5rem 0;
& > li {
& > a {
background-color: transparent;
}
}
}
& > .overflow {
max-height: unset;
& > li:last-of-type {
margin-bottom: 0;
}
&:after {
display: none;
& > li {
& > a {
background-color: transparent;
}
}
}
& > .overflow {
&:after {
display: none;
}
height: auto;
@media all and ($desktop) {
height: 250px;
}
}
}

View File

@ -1,10 +1,15 @@
@use "../../styles/variables.scss" as *;
.explorer {
display: flex;
flex-direction: column;
overflow-y: hidden;
&.desktop-only {
overflow-y: auto;
@media all and not ($mobile) {
display: flex;
}
}
&:after {
/*&:after {
pointer-events: none;
content: "";
width: 100%;
@ -15,7 +20,7 @@
opacity: 1;
transition: opacity 0.3s ease;
background: linear-gradient(transparent 0px, var(--light));
}
}*/
}
button#explorer {
@ -62,7 +67,8 @@ button#explorer {
#explorer-content {
list-style: none;
overflow: hidden;
max-height: none;
overflow-y: auto;
max-height: 100%;
transition:
max-height 0.35s ease,
visibility 0s linear 0s;
@ -70,6 +76,7 @@ button#explorer {
visibility: visible;
&.collapsed {
max-height: 0;
transition:
max-height 0.35s ease,
visibility 0s linear 0.35s;

View File

@ -1,5 +1,10 @@
.toc {
overflow-y: auto;
display: flex;
flex-direction: column;
&.desktop-only {
display: flex;
max-height: 40%;
}
}
button#toc {
@ -32,17 +37,19 @@ button#toc {
#toc-content {
list-style: none;
overflow: hidden;
max-height: none;
overflow-y: auto;
max-height: 100%;
transition:
max-height 0.5s ease,
max-height 0.35s ease,
visibility 0s linear 0s;
position: relative;
visibility: visible;
&.collapsed {
max-height: 0;
transition:
max-height 0.5s ease,
visibility 0s linear 0.5s;
max-height 0.35s ease,
visibility 0s linear 0.35s;
visibility: hidden;
}
@ -65,6 +72,10 @@ button#toc {
}
}
}
> ul.overflow {
max-height: none;
width: 100%;
}
@for $i from 0 through 6 {
& .depth-#{$i} {

View File

@ -19,6 +19,7 @@ import pt from "./locales/pt-BR"
import hu from "./locales/hu-HU"
import fa from "./locales/fa-IR"
import pl from "./locales/pl-PL"
import cs from "./locales/cs-CZ"
export const TRANSLATIONS = {
"en-US": enUs,
@ -62,6 +63,7 @@ export const TRANSLATIONS = {
"hu-HU": hu,
"fa-IR": fa,
"pl-PL": pl,
"cs-CZ": cs,
} as const
export const defaultTranslation = "en-US"

View File

@ -0,0 +1,84 @@
import { Translation } from "./definition"
export default {
propertyDefaults: {
title: "Bez názvu",
description: "Nebyl uveden žádný popis",
},
components: {
callout: {
note: "Poznámka",
abstract: "Abstract",
info: "Info",
todo: "Todo",
tip: "Tip",
success: "Úspěch",
question: "Otázka",
warning: "Upozornění",
failure: "Chyba",
danger: "Nebezpečí",
bug: "Bug",
example: "Příklad",
quote: "Citace",
},
backlinks: {
title: "Příchozí odkazy",
noBacklinksFound: "Nenalezeny žádné příchozí odkazy",
},
themeToggle: {
lightMode: "Světlý režim",
darkMode: "Tmavý režim",
},
explorer: {
title: "Procházet",
},
footer: {
createdWith: "Vytvořeno pomocí",
},
graph: {
title: "Graf",
},
recentNotes: {
title: "Nejnovější poznámky",
seeRemainingMore: ({ remaining }) => `Zobraz ${remaining} dalších →`,
},
transcludes: {
transcludeOf: ({ targetSlug }) => `Zobrazení ${targetSlug}`,
linkToOriginal: "Odkaz na původní dokument",
},
search: {
title: "Hledat",
searchBarPlaceholder: "Hledejte něco",
},
tableOfContents: {
title: "Obsah",
},
contentMeta: {
readingTime: ({ minutes }) => `${minutes} min čtení`,
},
},
pages: {
rss: {
recentNotes: "Nejnovější poznámky",
lastFewNotes: ({ count }) => `Posledních ${count} poznámek`,
},
error: {
title: "Nenalezeno",
notFound: "Tato stránka je buď soukromá, nebo neexistuje.",
home: "Návrat na domovskou stránku",
},
folderContent: {
folder: "Složka",
itemsUnderFolder: ({ count }) =>
count === 1 ? "1 položka v této složce." : `${count} položek v této složce.`,
},
tagContent: {
tag: "Tag",
tagIndex: "Rejstřík tagů",
itemsUnderTag: ({ count }) =>
count === 1 ? "1 položka s tímto tagem." : `${count} položek s tímto tagem.`,
showingFirst: ({ count }) => `Zobrazují se první ${count} tagy.`,
totalTags: ({ count }) => `Nalezeno celkem ${count} tagů.`,
},
},
} as const satisfies Translation

View File

@ -152,6 +152,15 @@ function addGlobalPageResources(ctx: BuildCtx, componentResources: ComponentReso
cabinScript.async = true
document.head.appendChild(cabinScript)
`)
} else if (cfg.analytics?.provider === "clarity") {
componentResources.afterDOMLoaded.push(`
const clarityScript = document.createElement("script")
clarityScript.innerHTML= \`(function(c,l,a,r,i,t,y){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "${cfg.analytics.projectId}");\`
document.head.appendChild(clarityScript)
`)
}
if (cfg.enableSPA) {

View File

@ -21,7 +21,7 @@ export const Citations: QuartzTransformerPlugin<Partial<Options>> = (userOpts) =
const opts = { ...defaultOptions, ...userOpts }
return {
name: "Citations",
htmlPlugins() {
htmlPlugins(ctx) {
const plugins: PluggableList = []
// Add rehype-citation to the list of plugins
@ -31,6 +31,8 @@ export const Citations: QuartzTransformerPlugin<Partial<Options>> = (userOpts) =
bibliography: opts.bibliographyFile,
suppressBibliography: opts.suppressBibliography,
linkCitations: opts.linkCitations,
csl: opts.csl,
lang: ctx.cfg.configuration.locale ?? "en-US",
},
])

View File

@ -119,7 +119,7 @@ export const tableWikilinkRegex = new RegExp(/(!?\[\[[^\]]*?\]\])/g)
const highlightRegex = new RegExp(/==([^=]+)==/g)
const commentRegex = new RegExp(/%%[\s\S]*?%%/g)
// from https://github.com/escwxyz/remark-obsidian-callout/blob/main/src/index.ts
const calloutRegex = new RegExp(/^\[\!(\w+)\|?(.+?)?\]([+-]?)/)
const calloutRegex = new RegExp(/^\[\!([\w-]+)\|?(.+?)?\]([+-]?)/)
const calloutLineRegex = new RegExp(/^> *\[\!\w+\|?.*?\][+-]?.*$/gm)
// (?:^| ) -> non-capturing group, tag should start be separated by a space or be the start of the line
// #(...) -> capturing group, tag itself must start with #
@ -430,7 +430,9 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>>
children: [
{
type: "text",
value: useDefaultTitle ? capitalize(typeString) : titleContent + " ",
value: useDefaultTitle
? capitalize(typeString).replace(/-/g, " ")
: titleContent + " ",
},
...restOfTitle,
],

View File

@ -182,7 +182,7 @@ a {
& .sidebar.left {
z-index: 1;
grid-area: sidebar-left;
grid-area: grid-sidebar-left;
flex-direction: column;
@media all and ($mobile) {
gap: 0;
@ -197,7 +197,7 @@ a {
}
& .sidebar.right {
grid-area: sidebar-right;
grid-area: grid-sidebar-right;
margin-right: 0;
flex-direction: column;
@media all and ($mobile) {
@ -224,7 +224,7 @@ a {
}
& .page-header {
grid-area: page-header;
grid-area: grid-header;
margin: $topSpacing 0 0 0;
@media all and ($mobile) {
margin-top: 0;
@ -233,15 +233,17 @@ a {
}
& .center > article {
grid-area: page-center;
grid-area: grid-center;
}
& .page-footer {
grid-area: page-footer;
& footer {
grid-area: grid-footer;
}
& .center,
& footer {
max-width: 100%;
min-width: 100%;
margin-left: auto;
margin-right: auto;
@media all and ($desktop) {
@ -408,7 +410,7 @@ pre {
counter-increment: line 0;
display: grid;
padding: 0.5rem 0;
overflow-x: scroll;
overflow-x: auto;
& [data-highlighted-chars] {
background-color: var(--highlight);
@ -527,12 +529,14 @@ video {
}
div:has(> .overflow) {
position: relative;
display: flex;
overflow-y: auto;
max-height: 100%;
}
ul.overflow,
ol.overflow {
max-height: 400;
max-height: 100%;
overflow-y: auto;
// clearfix
@ -542,8 +546,7 @@ ol.overflow {
& > li:last-of-type {
margin-bottom: 30px;
}
&:after {
/*&:after {
pointer-events: none;
content: "";
width: 100%;
@ -554,7 +557,7 @@ ol.overflow {
opacity: 1;
transition: opacity 0.3s ease;
background: linear-gradient(transparent 0px, var(--light));
}
}*/
}
.transclude {

View File

@ -27,11 +27,11 @@ $mobileGrid: (
rowGap: "5px",
columnGap: "5px",
templateAreas:
'"sidebar-left"\
"page-header"\
"page-center"\
"sidebar-right"\
"page-footer"',
'"grid-sidebar-left"\
"grid-header"\
"grid-center"\
"grid-sidebar-right"\
"grid-footer"',
);
$tabletGrid: (
templateRows: "auto auto auto auto",
@ -39,10 +39,10 @@ $tabletGrid: (
rowGap: "5px",
columnGap: "5px",
templateAreas:
'"sidebar-left page-header"\
"sidebar-left page-center"\
"sidebar-left sidebar-right"\
"sidebar-left page-footer"',
'"grid-sidebar-left grid-header"\
"grid-sidebar-left grid-center"\
"grid-sidebar-left grid-sidebar-right"\
"grid-sidebar-left grid-footer"',
);
$desktopGrid: (
templateRows: "auto auto auto",
@ -50,7 +50,7 @@ $desktopGrid: (
rowGap: "5px",
columnGap: "5px",
templateAreas:
'"sidebar-left page-header sidebar-right"\
"sidebar-left page-center sidebar-right"\
"sidebar-left page-footer sidebar-right"',
'"grid-sidebar-left grid-header grid-sidebar-right"\
"grid-sidebar-left grid-center grid-sidebar-right"\
"grid-sidebar-left grid-footer grid-sidebar-right"',
);