Compare commits

...

10 commits

Author SHA1 Message Date
53944f2e85 quartz state 2025-05-01 15:46:00 +00:00
anthops
adf442036b
fix(graph): provide proper workaround for pixijs webgpu issue #1899 (#1949) 2025-04-30 09:49:41 -07:00
badcode
dc2c4dca08
docs: add fix for 'remote end hung up unexpectedly' error during initial sync (#1939) 2025-04-29 09:55:15 -07:00
dralagen
6ba9c7c02a
doc(favicon): add documentation of favicon plugin (#1948)
* doc(favicon): add documentation of favicon plugin

* doc(favicon): add missing link to configuration page

* fix(favicon): build on public folder don't created
2025-04-28 22:00:28 -07:00
Stephen Tse
8d5b13ee03
fix(fonts): Fixed page title fonts not downloadable to local (#1898)
* Fixed url parser regex not working for Google Fonts subset API

* Prettier no
2025-04-28 14:58:06 -07:00
dependabot[bot]
4d07ac93b4
chore(deps-dev): bump the production-dependencies group with 2 updates (#1952)
Bumps the production-dependencies group with 2 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [esbuild](https://github.com/evanw/esbuild).


Updates `@types/node` from 22.14.1 to 22.15.3
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `esbuild` from 0.25.2 to 0.25.3
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.2...v0.25.3)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.15.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: esbuild
  dependency-version: 0.25.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-28 14:41:04 -07:00
Jacky Zhao
32d3fc0ce8 chore(ci): fix proj name 2025-04-28 14:35:51 -07:00
Jacky Zhao
00e860d8e6 ci: fix fork preview 2025-04-28 13:19:29 -07:00
Stephen Tse
2acdec323f
fix(explorer): Prevent html from being scrollable when mobile explorer is open (#1895)
* Fixed html page being scrollable when mobile explorer is open

* Prettier code

* Addressed comment
2025-04-26 11:13:56 -07:00
dralagen
9e58857746
feat(favicon): add plugin to expose favicon from icon.png (#1942)
* feat(favicon): add plugin to expose favicon from icon.png

* chore(favicon): clean up formatting and remove unnecessary line breaks
2025-04-26 11:06:59 -07:00
17 changed files with 301 additions and 157 deletions

View file

@ -36,11 +36,8 @@ jobs:
- name: Build Quartz - name: Build Quartz
run: npx quartz build -d docs -v run: npx quartz build -d docs -v
- name: Publish to Cloudflare Pages - name: Upload build artifact
uses: AdrianGonz97/refined-cf-pages-action@v1 uses: actions/upload-artifact@v4
with: with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} name: preview-build
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} path: public
githubToken: ${{ secrets.GITHUB_TOKEN }}
projectName: quartz
directory: public

37
.github/workflows/deploy-preview.yaml vendored Normal file
View file

@ -0,0 +1,37 @@
name: Upload Preview Deployment
on:
workflow_run:
workflows: ["Build Preview Deployment"]
types:
- completed
permissions:
actions: read
deployments: write
contents: read
pull-requests: write
jobs:
deploy-preview:
if: ${{ github.repository == 'jackyzha0/quartz' && github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
name: Deploy Preview to Cloudflare Pages
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
id: preview-build-artifact
with:
name: preview-build
path: build
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Deploy to Cloudflare Pages
uses: AdrianGonz97/refined-cf-pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
githubToken: ${{ secrets.GITHUB_TOKEN }}
projectName: quartz
deploymentName: Branch Preview
directory: ${{ steps.preview-build-artifact.outputs.download-path }}

View file

19
docs/plugins/Favicon.md Normal file
View file

@ -0,0 +1,19 @@
---
title: Favicon
tags:
- plugin/emitter
---
This plugin emits a `favicon.ico` into the `public` folder. It creates the favicon from `icon.png` located in the `quartz/static` folder.
The plugin resizes `icon.png` to 48x48px to make it as small as possible.
> [!note]
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
This plugin has no configuration options.
## API
- Category: Emitter
- Function name: `Plugin.Favicon()`.
- Source: [`quartz/plugins/emitters/favicon.ts`](https://github.com/jackyzha0/quartz/blob/v4/quartz/plugins/emitters/favicon.ts).

View file

@ -34,6 +34,13 @@ npx quartz sync --no-pull
> [!warning]- `fatal: --[no-]autostash option is only valid with --rebase` > [!warning]- `fatal: --[no-]autostash option is only valid with --rebase`
> You may have an outdated version of `git`. Updating `git` should fix this issue. > You may have an outdated version of `git`. Updating `git` should fix this issue.
> [!warning]- `fatal: The remote end hung up unexpectedly`
> It might be due to Git's default buffer size. You can fix it by increasing the buffer with this command:
>
> ```bash
> git config http.postBuffer 524288000
> ```
In future updates, you can simply run `npx quartz sync` every time you want to push updates to your repository. In future updates, you can simply run `npx quartz sync` every time you want to push updates to your repository.
> [!hint] Flags and options > [!hint] Flags and options

216
package-lock.json generated
View file

@ -81,12 +81,12 @@
"@types/d3": "^7.4.3", "@types/d3": "^7.4.3",
"@types/hast": "^3.0.4", "@types/hast": "^3.0.4",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/node": "^22.14.1", "@types/node": "^22.15.3",
"@types/pretty-time": "^1.1.5", "@types/pretty-time": "^1.1.5",
"@types/source-map-support": "^0.5.10", "@types/source-map-support": "^0.5.10",
"@types/ws": "^8.18.1", "@types/ws": "^8.18.1",
"@types/yargs": "^17.0.33", "@types/yargs": "^17.0.33",
"esbuild": "^0.25.2", "esbuild": "^0.25.3",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"tsx": "^4.19.3", "tsx": "^4.19.3",
"typescript": "^5.8.3" "typescript": "^5.8.3"
@ -210,9 +210,9 @@
} }
}, },
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz",
"integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@ -226,9 +226,9 @@
} }
}, },
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz",
"integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -242,9 +242,9 @@
} }
}, },
"node_modules/@esbuild/android-arm64": { "node_modules/@esbuild/android-arm64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz",
"integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -258,9 +258,9 @@
} }
}, },
"node_modules/@esbuild/android-x64": { "node_modules/@esbuild/android-x64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz",
"integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -274,9 +274,9 @@
} }
}, },
"node_modules/@esbuild/darwin-arm64": { "node_modules/@esbuild/darwin-arm64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz",
"integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -290,9 +290,9 @@
} }
}, },
"node_modules/@esbuild/darwin-x64": { "node_modules/@esbuild/darwin-x64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz",
"integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -306,9 +306,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-arm64": { "node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz",
"integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -322,9 +322,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-x64": { "node_modules/@esbuild/freebsd-x64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz",
"integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -338,9 +338,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm": { "node_modules/@esbuild/linux-arm": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz",
"integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -354,9 +354,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm64": { "node_modules/@esbuild/linux-arm64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz",
"integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -370,9 +370,9 @@
} }
}, },
"node_modules/@esbuild/linux-ia32": { "node_modules/@esbuild/linux-ia32": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz",
"integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -386,9 +386,9 @@
} }
}, },
"node_modules/@esbuild/linux-loong64": { "node_modules/@esbuild/linux-loong64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz",
"integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@ -402,9 +402,9 @@
} }
}, },
"node_modules/@esbuild/linux-mips64el": { "node_modules/@esbuild/linux-mips64el": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz",
"integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==",
"cpu": [ "cpu": [
"mips64el" "mips64el"
], ],
@ -418,9 +418,9 @@
} }
}, },
"node_modules/@esbuild/linux-ppc64": { "node_modules/@esbuild/linux-ppc64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz",
"integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@ -434,9 +434,9 @@
} }
}, },
"node_modules/@esbuild/linux-riscv64": { "node_modules/@esbuild/linux-riscv64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz",
"integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@ -450,9 +450,9 @@
} }
}, },
"node_modules/@esbuild/linux-s390x": { "node_modules/@esbuild/linux-s390x": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz",
"integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@ -466,9 +466,9 @@
} }
}, },
"node_modules/@esbuild/linux-x64": { "node_modules/@esbuild/linux-x64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz",
"integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -482,9 +482,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-arm64": { "node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz",
"integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -498,9 +498,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-x64": { "node_modules/@esbuild/netbsd-x64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz",
"integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -514,9 +514,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-arm64": { "node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz",
"integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -530,9 +530,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-x64": { "node_modules/@esbuild/openbsd-x64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz",
"integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -546,9 +546,9 @@
} }
}, },
"node_modules/@esbuild/sunos-x64": { "node_modules/@esbuild/sunos-x64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz",
"integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -562,9 +562,9 @@
} }
}, },
"node_modules/@esbuild/win32-arm64": { "node_modules/@esbuild/win32-arm64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz",
"integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -578,9 +578,9 @@
} }
}, },
"node_modules/@esbuild/win32-ia32": { "node_modules/@esbuild/win32-ia32": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz",
"integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -594,9 +594,9 @@
} }
}, },
"node_modules/@esbuild/win32-x64": { "node_modules/@esbuild/win32-x64": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz",
"integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1942,9 +1942,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.14.1", "version": "22.15.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz",
"integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2942,9 +2942,9 @@
} }
}, },
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.25.2", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz",
"integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
@ -2954,31 +2954,31 @@
"node": ">=18" "node": ">=18"
}, },
"optionalDependencies": { "optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.2", "@esbuild/aix-ppc64": "0.25.3",
"@esbuild/android-arm": "0.25.2", "@esbuild/android-arm": "0.25.3",
"@esbuild/android-arm64": "0.25.2", "@esbuild/android-arm64": "0.25.3",
"@esbuild/android-x64": "0.25.2", "@esbuild/android-x64": "0.25.3",
"@esbuild/darwin-arm64": "0.25.2", "@esbuild/darwin-arm64": "0.25.3",
"@esbuild/darwin-x64": "0.25.2", "@esbuild/darwin-x64": "0.25.3",
"@esbuild/freebsd-arm64": "0.25.2", "@esbuild/freebsd-arm64": "0.25.3",
"@esbuild/freebsd-x64": "0.25.2", "@esbuild/freebsd-x64": "0.25.3",
"@esbuild/linux-arm": "0.25.2", "@esbuild/linux-arm": "0.25.3",
"@esbuild/linux-arm64": "0.25.2", "@esbuild/linux-arm64": "0.25.3",
"@esbuild/linux-ia32": "0.25.2", "@esbuild/linux-ia32": "0.25.3",
"@esbuild/linux-loong64": "0.25.2", "@esbuild/linux-loong64": "0.25.3",
"@esbuild/linux-mips64el": "0.25.2", "@esbuild/linux-mips64el": "0.25.3",
"@esbuild/linux-ppc64": "0.25.2", "@esbuild/linux-ppc64": "0.25.3",
"@esbuild/linux-riscv64": "0.25.2", "@esbuild/linux-riscv64": "0.25.3",
"@esbuild/linux-s390x": "0.25.2", "@esbuild/linux-s390x": "0.25.3",
"@esbuild/linux-x64": "0.25.2", "@esbuild/linux-x64": "0.25.3",
"@esbuild/netbsd-arm64": "0.25.2", "@esbuild/netbsd-arm64": "0.25.3",
"@esbuild/netbsd-x64": "0.25.2", "@esbuild/netbsd-x64": "0.25.3",
"@esbuild/openbsd-arm64": "0.25.2", "@esbuild/openbsd-arm64": "0.25.3",
"@esbuild/openbsd-x64": "0.25.2", "@esbuild/openbsd-x64": "0.25.3",
"@esbuild/sunos-x64": "0.25.2", "@esbuild/sunos-x64": "0.25.3",
"@esbuild/win32-arm64": "0.25.2", "@esbuild/win32-arm64": "0.25.3",
"@esbuild/win32-ia32": "0.25.2", "@esbuild/win32-ia32": "0.25.3",
"@esbuild/win32-x64": "0.25.2" "@esbuild/win32-x64": "0.25.3"
} }
}, },
"node_modules/esbuild-sass-plugin": { "node_modules/esbuild-sass-plugin": {

View file

@ -104,12 +104,12 @@
"@types/d3": "^7.4.3", "@types/d3": "^7.4.3",
"@types/hast": "^3.0.4", "@types/hast": "^3.0.4",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/node": "^22.14.1", "@types/node": "^22.15.3",
"@types/pretty-time": "^1.1.5", "@types/pretty-time": "^1.1.5",
"@types/source-map-support": "^0.5.10", "@types/source-map-support": "^0.5.10",
"@types/ws": "^8.18.1", "@types/ws": "^8.18.1",
"@types/yargs": "^17.0.33", "@types/yargs": "^17.0.33",
"esbuild": "^0.25.2", "esbuild": "^0.25.3",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"tsx": "^4.19.3", "tsx": "^4.19.3",
"typescript": "^5.8.3" "typescript": "^5.8.3"

View file

@ -8,23 +8,22 @@ import * as Plugin from "./quartz/plugins"
*/ */
const config: QuartzConfig = { const config: QuartzConfig = {
configuration: { configuration: {
pageTitle: "Quartz 4", pageTitle: "Speisekarten Explorer",
pageTitleSuffix: "", pageTitleSuffix: "",
enableSPA: true, enableSPA: true,
enablePopovers: true, enablePopovers: true,
analytics: { analytics: {
provider: "plausible",
}, },
locale: "en-US", locale: "en-US",
baseUrl: "quartz.jzhao.xyz", baseUrl: "menus.byte.wtf",
ignorePatterns: ["private", "templates", ".obsidian"], ignorePatterns: ["private", "templates", ".obsidian"],
defaultDateType: "modified", defaultDateType: "modified",
theme: { theme: {
fontOrigin: "googleFonts", fontOrigin: "googleFonts",
cdnCaching: true, cdnCaching: false,
typography: { typography: {
header: "Schibsted Grotesk", header: "Roboto",
body: "Source Sans Pro", body: "Roboto Mono",
code: "IBM Plex Mono", code: "IBM Plex Mono",
}, },
colors: { colors: {
@ -45,8 +44,8 @@ const config: QuartzConfig = {
gray: "#646464", gray: "#646464",
darkgray: "#d4d4d4", darkgray: "#d4d4d4",
dark: "#ebebec", dark: "#ebebec",
secondary: "#7b97aa", secondary: "#FD3656",
tertiary: "#84a59d", tertiary: "#31FEFD",
highlight: "rgba(143, 159, 169, 0.15)", highlight: "rgba(143, 159, 169, 0.15)",
textHighlight: "#b3aa0288", textHighlight: "#b3aa0288",
}, },
@ -86,6 +85,7 @@ const config: QuartzConfig = {
}), }),
Plugin.Assets(), Plugin.Assets(),
Plugin.Static(), Plugin.Static(),
Plugin.Favicon(),
Plugin.NotFoundPage(), Plugin.NotFoundPage(),
// Comment out CustomOgImages to speed up build time // Comment out CustomOgImages to speed up build time
Plugin.CustomOgImages(), Plugin.CustomOgImages(),

View file

@ -6,12 +6,7 @@ export const sharedPageComponents: SharedLayout = {
head: Component.Head(), head: Component.Head(),
header: [], header: [],
afterBody: [], afterBody: [],
footer: Component.Footer({ footer: Component.Spacer(),
links: {
GitHub: "https://github.com/jackyzha0/quartz",
"Discord Community": "https://discord.gg/cRFFHYye7t",
},
}),
} }
// components for pages that display a single page (e.g. a single note) // components for pages that display a single page (e.g. a single note)

View file

@ -246,9 +246,8 @@ export function renderPage(
))} ))}
</Header> </Header>
<div class="popover-hint"> <div class="popover-hint">
{beforeBody.map((BodyComponent) => ( {slug !== "index" &&
<BodyComponent {...componentData} /> beforeBody.map((BodyComponent) => <BodyComponent {...componentData} />)}
))}
</div> </div>
</div> </div>
<Content {...componentData} /> <Content {...componentData} />

View file

@ -23,11 +23,18 @@ let currentExplorerState: Array<FolderState>
function toggleExplorer(this: HTMLElement) { function toggleExplorer(this: HTMLElement) {
const nearestExplorer = this.closest(".explorer") as HTMLElement const nearestExplorer = this.closest(".explorer") as HTMLElement
if (!nearestExplorer) return if (!nearestExplorer) return
nearestExplorer.classList.toggle("collapsed") const explorerCollapsed = nearestExplorer.classList.toggle("collapsed")
nearestExplorer.setAttribute( nearestExplorer.setAttribute(
"aria-expanded", "aria-expanded",
nearestExplorer.getAttribute("aria-expanded") === "true" ? "false" : "true", nearestExplorer.getAttribute("aria-expanded") === "true" ? "false" : "true",
) )
if (!explorerCollapsed) {
// Stop <html> from being scrollable when mobile explorer is open
document.documentElement.classList.add("mobile-no-scroll")
} else {
document.documentElement.classList.remove("mobile-no-scroll")
}
} }
function toggleFolder(evt: MouseEvent) { function toggleFolder(evt: MouseEvent) {
@ -270,12 +277,25 @@ document.addEventListener("nav", async (e: CustomEventMap["nav"]) => {
if (mobileExplorer.checkVisibility()) { if (mobileExplorer.checkVisibility()) {
explorer.classList.add("collapsed") explorer.classList.add("collapsed")
explorer.setAttribute("aria-expanded", "false") explorer.setAttribute("aria-expanded", "false")
// Allow <html> to be scrollable when mobile explorer is collapsed
document.documentElement.classList.remove("mobile-no-scroll")
} }
mobileExplorer.classList.remove("hide-until-loaded") mobileExplorer.classList.remove("hide-until-loaded")
} }
}) })
window.addEventListener("resize", function () {
// Desktop explorer opens by default, and it stays open when the window is resized
// to mobile screen size. Applies `no-scroll` to <html> in this edge case.
const explorer = document.querySelector(".explorer")
if (explorer && !explorer.classList.contains("collapsed")) {
document.documentElement.classList.add("mobile-no-scroll")
return
}
})
function setFolderState(folderElement: HTMLElement, collapsed: boolean) { function setFolderState(folderElement: HTMLElement, collapsed: boolean) {
return collapsed ? folderElement.classList.remove("open") : folderElement.classList.add("open") return collapsed ? folderElement.classList.remove("open") : folderElement.classList.add("open")
} }

View file

@ -68,13 +68,28 @@ type TweenNode = {
stop: () => void stop: () => void
} }
// workaround for pixijs webgpu issue: https://github.com/pixijs/pixijs/issues/11389
async function determineGraphicsAPI(): Promise<"webgpu" | "webgl"> { async function determineGraphicsAPI(): Promise<"webgpu" | "webgl"> {
const adapter = await navigator.gpu?.requestAdapter().catch(() => null) const adapter = await navigator.gpu?.requestAdapter().catch(() => null)
if (!adapter) { const device = adapter && (await adapter.requestDevice().catch(() => null))
if (!device) {
return "webgl" return "webgl"
} }
// Devices with WebGPU but no float32-blendable feature fail to render the graph
return adapter.features.has("float32-blendable") ? "webgpu" : "webgl" const canvas = document.createElement("canvas")
const gl =
(canvas.getContext("webgl2") as WebGL2RenderingContext | null) ??
(canvas.getContext("webgl") as WebGLRenderingContext | null)
// we have to return webgl so pixijs automatically falls back to canvas
if (!gl) {
return "webgl"
}
const webglMaxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)
const webgpuMaxTextures = device.limits.maxSampledTexturesPerShaderStage
return webglMaxTextures === webgpuMaxTextures ? "webgpu" : "webgl"
} }
async function renderGraph(graph: HTMLElement, fullSlug: FullSlug) { async function renderGraph(graph: HTMLElement, fullSlug: FullSlug) {

View file

@ -263,22 +263,8 @@ li:has(> .folder-outer:not(.open)) > .folder-container > svg {
} }
} }
.no-scroll { .mobile-no-scroll {
opacity: 0; @media all and ($mobile) {
overflow: hidden; overflow: hidden;
}
html:has(.no-scroll) {
overflow: hidden;
}
@media all and not ($mobile) {
.no-scroll {
opacity: 1 !important;
overflow: auto !important;
}
html:has(.no-scroll) {
overflow: auto !important;
} }
} }

View file

@ -0,0 +1,22 @@
import sharp from "sharp"
import { joinSegments, QUARTZ, FullSlug } from "../../util/path"
import { QuartzEmitterPlugin } from "../types"
import { write } from "./helpers"
import { BuildCtx } from "../../util/ctx"
export const Favicon: QuartzEmitterPlugin = () => ({
name: "Favicon",
async *emit({ argv }) {
const iconPath = joinSegments(QUARTZ, "static", "icon.png")
const faviconContent = sharp(iconPath).resize(48, 48).toFormat("png")
yield write({
ctx: { argv } as BuildCtx,
slug: "favicon" as FullSlug,
ext: ".ico",
content: faviconContent,
})
},
async *partialEmit() {},
})

View file

@ -5,6 +5,7 @@ export { ContentIndex as ContentIndex } from "./contentIndex"
export { AliasRedirects } from "./aliases" export { AliasRedirects } from "./aliases"
export { Assets } from "./assets" export { Assets } from "./assets"
export { Static } from "./static" export { Static } from "./static"
export { Favicon } from "./favicon"
export { ComponentResources } from "./componentResources" export { ComponentResources } from "./componentResources"
export { NotFoundPage } from "./404" export { NotFoundPage } from "./404"
export { CNAME } from "./cname" export { CNAME } from "./cname"

View file

@ -1,3 +1,40 @@
@use "./base.scss"; @use "./base.scss";
// put your custom CSS here! // put your custom CSS here!
// hide date for subfolders on folderpage
.page-listing {
li.section-li:has(.section .desc) {
.meta {
// hides date, keep indent
visibility: hidden;
}
.section {
grid-template-columns: none;
}
}
}
.page-header div.popover-hint p.content-meta {
display: none;
}
.popover-hint div.page-listing p {
display: none;
}
// indicate folder more clearly on folderpage
.page-listing {
li.section-li:has(.section .desc a.internal[href$="/"]) {
.desc a.internal {
// prepend folder emoji
&:before {
content: "📁";
font-size: 2em;
}
}
}
}
// hide Date if frontmatter contains cssclasses hideDate
body:has(.page-header ~ article.hideDate) .content-meta {
display: none;
}

View file

@ -107,6 +107,13 @@ export interface GoogleFontFile {
extension: string extension: string
} }
const fontMimeMap: Record<string, string> = {
truetype: "ttf",
woff: "woff",
woff2: "woff2",
opentype: "otf",
}
export async function processGoogleFonts( export async function processGoogleFonts(
stylesheet: string, stylesheet: string,
baseUrl: string, baseUrl: string,
@ -114,14 +121,16 @@ export async function processGoogleFonts(
processedStylesheet: string processedStylesheet: string
fontFiles: GoogleFontFile[] fontFiles: GoogleFontFile[]
}> { }> {
const fontSourceRegex = /url\((https:\/\/fonts.gstatic.com\/s\/[^)]+\.(woff2|ttf))\)/g const fontSourceRegex =
/url\((https:\/\/fonts.gstatic.com\/.+(?:\/|(?:kit=))(.+?)[.&].+?)\)\sformat\('(\w+?)'\);/g
const fontFiles: GoogleFontFile[] = [] const fontFiles: GoogleFontFile[] = []
let processedStylesheet = stylesheet let processedStylesheet = stylesheet
let match let match
while ((match = fontSourceRegex.exec(stylesheet)) !== null) { while ((match = fontSourceRegex.exec(stylesheet)) !== null) {
const url = match[1] const url = match[1]
const [filename, extension] = url.split("/").pop()!.split(".") const filename = match[2]
const extension = fontMimeMap[match[3].toLowerCase()]
const staticUrl = `https://${baseUrl}/static/fonts/${filename}.${extension}` const staticUrl = `https://${baseUrl}/static/fonts/${filename}.${extension}`
processedStylesheet = processedStylesheet.replace(url, staticUrl) processedStylesheet = processedStylesheet.replace(url, staticUrl)