mirror of
https://github.com/jackyzha0/quartz.git
synced 2026-03-24 23:15:46 -05:00
Merge branch 'v4' of https://github.com/jackyzha0/quartz
This commit is contained in:
commit
0f0653ef24
2
globals.d.ts
vendored
2
globals.d.ts
vendored
@ -4,7 +4,7 @@ export declare global {
|
||||
type: K,
|
||||
listener: (this: Document, ev: CustomEventMap[K]) => void,
|
||||
): void
|
||||
dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K]): void
|
||||
dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K] | UIEvent): void
|
||||
}
|
||||
interface Window {
|
||||
spaNavigate(url: URL, isBack: boolean = false)
|
||||
|
||||
130
package-lock.json
generated
130
package-lock.json
generated
@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^0.7.0",
|
||||
"@floating-ui/dom": "^1.5.3",
|
||||
"@napi-rs/simple-git": "0.1.11",
|
||||
"@napi-rs/simple-git": "0.1.14",
|
||||
"async-mutex": "^0.4.0",
|
||||
"chalk": "^5.3.0",
|
||||
"chokidar": "^3.5.3",
|
||||
@ -49,9 +49,9 @@
|
||||
"remark-gfm": "^4.0.0",
|
||||
"remark-math": "^6.0.0",
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.0.0",
|
||||
"remark-rehype": "^11.1.0",
|
||||
"remark-smartypants": "^2.0.0",
|
||||
"rfdc": "^1.3.0",
|
||||
"rfdc": "^1.3.1",
|
||||
"rimraf": "^5.0.5",
|
||||
"serve-handler": "^6.1.5",
|
||||
"shikiji": "^0.10.2",
|
||||
@ -61,7 +61,7 @@
|
||||
"unified": "^11.0.4",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"vfile": "^6.0.1",
|
||||
"workerpool": "^8.0.0",
|
||||
"workerpool": "^9.1.0",
|
||||
"ws": "^8.15.1",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
@ -76,7 +76,6 @@
|
||||
"@types/node": "^20.1.2",
|
||||
"@types/pretty-time": "^1.1.5",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"@types/workerpool": "^6.4.7",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@types/yargs": "^17.0.32",
|
||||
"esbuild": "^0.19.9",
|
||||
@ -517,30 +516,30 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git/-/simple-git-0.1.11.tgz",
|
||||
"integrity": "sha512-z14cPCBrtDKKVJ3q4GS5gmXEithGUAt+U8sICgA9i3UFdxJKD4H5rCnO7BVC3htdE9g6OR2w2IcHAL56AjpFbg==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git/-/simple-git-0.1.14.tgz",
|
||||
"integrity": "sha512-2cDnsT0nKpQ7yg5u/Zf8/ibp9YFIKhpcfMAGATYuqdJoHuBo6P6UArZ0RDOOtfFC5b9FXuYcGw2ApbM4eWdnbQ==",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@napi-rs/simple-git-android-arm-eabi": "0.1.11",
|
||||
"@napi-rs/simple-git-android-arm64": "0.1.11",
|
||||
"@napi-rs/simple-git-darwin-arm64": "0.1.11",
|
||||
"@napi-rs/simple-git-darwin-x64": "0.1.11",
|
||||
"@napi-rs/simple-git-linux-arm-gnueabihf": "0.1.11",
|
||||
"@napi-rs/simple-git-linux-arm64-gnu": "0.1.11",
|
||||
"@napi-rs/simple-git-linux-arm64-musl": "0.1.11",
|
||||
"@napi-rs/simple-git-linux-x64-gnu": "0.1.11",
|
||||
"@napi-rs/simple-git-linux-x64-musl": "0.1.11",
|
||||
"@napi-rs/simple-git-win32-arm64-msvc": "0.1.11",
|
||||
"@napi-rs/simple-git-win32-x64-msvc": "0.1.11"
|
||||
"@napi-rs/simple-git-android-arm-eabi": "0.1.14",
|
||||
"@napi-rs/simple-git-android-arm64": "0.1.14",
|
||||
"@napi-rs/simple-git-darwin-arm64": "0.1.14",
|
||||
"@napi-rs/simple-git-darwin-x64": "0.1.14",
|
||||
"@napi-rs/simple-git-linux-arm-gnueabihf": "0.1.14",
|
||||
"@napi-rs/simple-git-linux-arm64-gnu": "0.1.14",
|
||||
"@napi-rs/simple-git-linux-arm64-musl": "0.1.14",
|
||||
"@napi-rs/simple-git-linux-x64-gnu": "0.1.14",
|
||||
"@napi-rs/simple-git-linux-x64-musl": "0.1.14",
|
||||
"@napi-rs/simple-git-win32-arm64-msvc": "0.1.14",
|
||||
"@napi-rs/simple-git-win32-x64-msvc": "0.1.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-android-arm-eabi": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.11.tgz",
|
||||
"integrity": "sha512-wt4Wu9MxvKzEqT4iwodFs7Nrc31K73gR5hM7VnlO6iLELmUQZ5JVJkYoFWgzLQWtzIC48W2+zFMbBgY6+F2rZg==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.14.tgz",
|
||||
"integrity": "sha512-fAJ/Hxc9DhtSHOcB3dPCRW1YcVsqAnbNoOOnHir4aDCtqTP64HrFa7A/675v3vQZpI0u3fXHRcYqW8NF0O/zcg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -553,9 +552,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-android-arm64": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.11.tgz",
|
||||
"integrity": "sha512-5/Aj6N44CxwhV3TZWRZ4vGqFj4wb2/a2gwvUZJo9Dwik9Spls7As8LaLe7pOptiGPH0GRP3H5kTT7I6twHNgqw==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.14.tgz",
|
||||
"integrity": "sha512-dav730MRAR142DoyNDafuwKXcUCYwlbxxxxOarDph7bbN0mZZnKHOQohvRCD/Uz4aJLaj6khCavXSjLDWArEUg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -568,9 +567,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-darwin-arm64": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.11.tgz",
|
||||
"integrity": "sha512-vdVsJUNcRsGVu0hBmLZdxxgwIbJA/Ias8NKWze8MZkZ3VyBwhg0uAzFgESEL3/USAgeCCHjF3uwVki8E+iPq1w==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.14.tgz",
|
||||
"integrity": "sha512-f6+DqRnI+vFvnsAyw66mWhwl0vw1TOieHV07hvKbg4PU5j+RBI+lVqwY2L+IEAxDFlPirTWKKvGY1Lr7M/yi/A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -583,9 +582,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-darwin-x64": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.11.tgz",
|
||||
"integrity": "sha512-ufVuZxyJ3LpApk3V101X9qYNX91fnQ4isulz9lWjg90U7Xz0Cav4J3yyFZy6B/cJpYxuiy49R8wV1xDtTeGThA==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.14.tgz",
|
||||
"integrity": "sha512-x/EnwJdDWJAFay8TQt09byJoBlVZhPEaTAPmRR0fUPzWTjrr28bOy8UW1ysszd9ylBxlyIhuWjOHMHu9CBigTQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -598,9 +597,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-linux-arm-gnueabihf": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.11.tgz",
|
||||
"integrity": "sha512-rFafW0Qc/j5we2ghUecB7mFzGcNDtJ5lTiB4I7kffNeL8pEi6Yi7kST8hylswcCowia65d45xsyeNp1mFlFwcg==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.14.tgz",
|
||||
"integrity": "sha512-k0JZaXBl031gP5VOnoMa1I3lCHlBG7QvtunX5rxnRjx2kZ+JgUyT12s/qle/4xkJ0MnmfKTeiD7hs4Cc4Z3Tzw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -613,9 +612,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-linux-arm64-gnu": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.11.tgz",
|
||||
"integrity": "sha512-HZ4yaqpj/FQ3V9qNQrTGhtXb7pLAARXeRJrwoaGfz3eZ069y2bHReFcNR//5bsVhZ18JaS9EV47F8WjDxtpI5g==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.14.tgz",
|
||||
"integrity": "sha512-CsmKP6tSIxau10ZKxV1Q1kem2QcJ/Qlov7pxp1Q7kMErcouW0H6vliVniewicaXRVDYV9wK18iD2t5GoJttwlA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -628,9 +627,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-linux-arm64-musl": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.11.tgz",
|
||||
"integrity": "sha512-b39lJiC3n2+Y6Exjx6qwHoBF++D3k2hN4mZZkvQCFSdLXJ2xtalCatSRWW3pt+mHOHMOgbGektL5v5BYq52hxw==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.14.tgz",
|
||||
"integrity": "sha512-krfEckZQ3myoHwmGmqY0aHBnqAzzV66+jFNLQEKaVMSGsXA2P+UcGo0coGzmB13rFRWC2eZpZRNB3MrfrStHkw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -643,9 +642,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-linux-x64-gnu": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.11.tgz",
|
||||
"integrity": "sha512-9EPFvY7PZg+oqWi6Jft5WgSsQtvy9Ey1g4NG+LG8y1RbvaNKthxKbR5zgx196pnFVdcLtsuIdOv/OaQlbcTXkw==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.14.tgz",
|
||||
"integrity": "sha512-4T2Q2QdO6t3OawkwdVmdqLz2EH8lfAw2cMT/zdjfTMfhNKjJgSg3kTgRnu/tf8TLCb+wu80fFvafwE0laB2VTQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -658,9 +657,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-linux-x64-musl": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.11.tgz",
|
||||
"integrity": "sha512-doIt1lPYIGL3UthlEQjdM9s1Wv0v8bz8LVAgbzJMS+UpVZzArwLWkanAJCy1HjgMTUMiE3AVJqACKIF3EfW/TQ==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.14.tgz",
|
||||
"integrity": "sha512-RaTGW8u+RXJbfRF4QN2Dcr5r5DrFh4wLjOvFeOy7sGX3Q9m3IKuw5AjRxTJqIw6xD/AAPKKNzOvPjrIF7728Lw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -673,9 +672,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-win32-arm64-msvc": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.11.tgz",
|
||||
"integrity": "sha512-TK3Uvj3Q72ebxfxDT/eLFt8sxCNHo20QMvqJ5BHt4zP1Y9Fl1DXSPRUKLBIhJd0nPcI45ZOMRiZyoT8joxAC9g==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.14.tgz",
|
||||
"integrity": "sha512-kb9bKG9t79HJMuRMqbUJFLfWRf952O2Ea4VFwoRA2d/Uwtowm85Ol3JV9E6oeurguRLqdMLrUKyduCW6Hc9Jsg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -688,9 +687,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/simple-git-win32-x64-msvc": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.11.tgz",
|
||||
"integrity": "sha512-XOgP6kFDXGmB2KCXFQEsCq70n/Do2h7W9o7qZu8APAD+Sc8JGKz4hKG7PKY2ot924v9nIoKSYbHnupnhXSoXkg==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.14.tgz",
|
||||
"integrity": "sha512-3835xy0e2gOaZ3SPt1pINBFSBBL3dOx3cChyAzQU0TnMU4Ye/YOh1qa5pO7BOJlCSnOh7iWt782blxCT0HH61w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1114,15 +1113,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
||||
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
|
||||
},
|
||||
"node_modules/@types/workerpool": {
|
||||
"version": "6.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/workerpool/-/workerpool-6.4.7.tgz",
|
||||
"integrity": "sha512-DI2U4obcMzFViyNjLw0xXspim++qkAJ4BWRdYPVMMFtOpTvMr6PAk3UTZEoSqnZnvgUkJ3ck97Ybk+iIfuJHMg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
|
||||
@ -4854,9 +4844,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/remark-rehype": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.0.0.tgz",
|
||||
"integrity": "sha512-vx8x2MDMcxuE4lBmQ46zYUDfcFMmvg80WYX+UNLeG6ixjdCCLcw1lrgAukwBTuOFsS78eoAedHGn9sNM0w7TPw==",
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz",
|
||||
"integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==",
|
||||
"dependencies": {
|
||||
"@types/hast": "^3.0.0",
|
||||
"@types/mdast": "^4.0.0",
|
||||
@ -5171,9 +5161,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
|
||||
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz",
|
||||
"integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg=="
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "5.0.5",
|
||||
@ -6069,9 +6059,9 @@
|
||||
"integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw=="
|
||||
},
|
||||
"node_modules/workerpool": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-8.0.0.tgz",
|
||||
"integrity": "sha512-aoLtwqMXoYVA1JV+t8uCLo7sXkF4Q1Ijrn7954X2IVyysk2bv2Il7C9sVJH8xk9xJAL0FNgR+hPOhmvnMk/P5Q=="
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.1.0.tgz",
|
||||
"integrity": "sha512-+wRWfm9yyJghvXLSHMQj3WXDxHbibHAQmRrWbqKBfy0RjftZNeQaW+Std5bSYc83ydkrxoPTPOWVlXUR9RWJdQ=="
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "8.1.0",
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^0.7.0",
|
||||
"@floating-ui/dom": "^1.5.3",
|
||||
"@napi-rs/simple-git": "0.1.11",
|
||||
"@napi-rs/simple-git": "0.1.14",
|
||||
"async-mutex": "^0.4.0",
|
||||
"chalk": "^5.3.0",
|
||||
"chokidar": "^3.5.3",
|
||||
@ -74,9 +74,9 @@
|
||||
"remark-gfm": "^4.0.0",
|
||||
"remark-math": "^6.0.0",
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.0.0",
|
||||
"remark-rehype": "^11.1.0",
|
||||
"remark-smartypants": "^2.0.0",
|
||||
"rfdc": "^1.3.0",
|
||||
"rfdc": "^1.3.1",
|
||||
"rimraf": "^5.0.5",
|
||||
"serve-handler": "^6.1.5",
|
||||
"shikiji": "^0.10.2",
|
||||
@ -86,7 +86,7 @@
|
||||
"unified": "^11.0.4",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"vfile": "^6.0.1",
|
||||
"workerpool": "^8.0.0",
|
||||
"workerpool": "^9.1.0",
|
||||
"ws": "^8.15.1",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
@ -98,7 +98,6 @@
|
||||
"@types/node": "^20.1.2",
|
||||
"@types/pretty-time": "^1.1.5",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"@types/workerpool": "^6.4.7",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@types/yargs": "^17.0.32",
|
||||
"esbuild": "^0.19.9",
|
||||
|
||||
@ -16,6 +16,7 @@ export type Analytics =
|
||||
| {
|
||||
provider: "umami"
|
||||
websiteId: string
|
||||
host?: string
|
||||
}
|
||||
|
||||
export interface GlobalConfiguration {
|
||||
@ -35,6 +36,12 @@ export interface GlobalConfiguration {
|
||||
*/
|
||||
baseUrl?: string
|
||||
theme: Theme
|
||||
/**
|
||||
* The locale to use for date formatting. Default to "en-US"
|
||||
* Allow to translate the date in the language of your choice.
|
||||
* Need to be formated following the IETF language tag format (https://en.wikipedia.org/wiki/IETF_language_tag)
|
||||
*/
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export interface QuartzConfig {
|
||||
|
||||
@ -347,7 +347,7 @@ export async function handleBuild(argv) {
|
||||
directoryListing: false,
|
||||
headers: [
|
||||
{
|
||||
source: "**/*.html",
|
||||
source: "**/*.*",
|
||||
headers: [{ key: "Content-Disposition", value: "inline" }],
|
||||
},
|
||||
],
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
function ArticleTitle({ fileData, displayClass }: QuartzComponentProps) {
|
||||
const title = fileData.frontmatter?.title
|
||||
if (title) {
|
||||
return <h1 class={`article-title ${displayClass ?? ""}`}>{title}</h1>
|
||||
return <h1 class={classNames(displayClass, "article-title")}>{title}</h1>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import style from "./styles/backlinks.scss"
|
||||
import { resolveRelative, simplifySlug } from "../util/path"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
function Backlinks({ fileData, allFiles, displayClass }: QuartzComponentProps) {
|
||||
const slug = simplifySlug(fileData.slug!)
|
||||
const backlinkFiles = allFiles.filter((file) => file.links?.includes(slug))
|
||||
return (
|
||||
<div class={`backlinks ${displayClass ?? ""}`}>
|
||||
<div class={classNames(displayClass, "backlinks")}>
|
||||
<h3>Backlinks</h3>
|
||||
<ul class="overflow">
|
||||
{backlinkFiles.length > 0 ? (
|
||||
|
||||
@ -2,6 +2,7 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import breadcrumbsStyle from "./styles/breadcrumbs.scss"
|
||||
import { FullSlug, SimpleSlug, resolveRelative } from "../util/path"
|
||||
import { QuartzPluginData } from "../plugins/vfile"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
type CrumbData = {
|
||||
displayName: string
|
||||
@ -113,7 +114,7 @@ export default ((opts?: Partial<BreadcrumbOptions>) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<nav class={`breadcrumb-container ${displayClass ?? ""}`} aria-label="breadcrumbs">
|
||||
<nav class={classNames(displayClass, "breadcrumb-container")} aria-label="breadcrumbs">
|
||||
{crumbs.map((crumb, index) => (
|
||||
<div class="breadcrumb-element">
|
||||
<a href={crumb.path}>{crumb.displayName}</a>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { formatDate, getDate } from "./Date"
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import readingTime from "reading-time"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
interface ContentMetaOptions {
|
||||
/**
|
||||
@ -24,7 +25,7 @@ export default ((opts?: Partial<ContentMetaOptions>) => {
|
||||
const segments: string[] = []
|
||||
|
||||
if (fileData.dates) {
|
||||
segments.push(formatDate(getDate(cfg, fileData)!))
|
||||
segments.push(formatDate(getDate(cfg, fileData)!, cfg.locale))
|
||||
}
|
||||
|
||||
// Display reading time if enabled
|
||||
@ -33,7 +34,7 @@ export default ((opts?: Partial<ContentMetaOptions>) => {
|
||||
segments.push(timeTaken)
|
||||
}
|
||||
|
||||
return <p class={`content-meta ${displayClass ?? ""}`}>{segments.join(", ")}</p>
|
||||
return <p class={classNames(displayClass, "content-meta")}>{segments.join(", ")}</p>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
|
||||
@ -4,10 +4,11 @@
|
||||
import darkmodeScript from "./scripts/darkmode.inline"
|
||||
import styles from "./styles/darkmode.scss"
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
function Darkmode({ displayClass }: QuartzComponentProps) {
|
||||
return (
|
||||
<div class={`darkmode ${displayClass ?? ""}`}>
|
||||
<div class={classNames(displayClass, "darkmode")}>
|
||||
<input class="toggle" id="darkmode-toggle" type="checkbox" tabIndex={-1} />
|
||||
<label id="toggle-label-light" for="darkmode-toggle" tabIndex={-1}>
|
||||
<svg
|
||||
|
||||
@ -3,6 +3,7 @@ import { QuartzPluginData } from "../plugins/vfile"
|
||||
|
||||
interface Props {
|
||||
date: Date
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export type ValidDateType = keyof Required<QuartzPluginData>["dates"]
|
||||
@ -16,14 +17,14 @@ export function getDate(cfg: GlobalConfiguration, data: QuartzPluginData): Date
|
||||
return data.dates?.[cfg.defaultDateType]
|
||||
}
|
||||
|
||||
export function formatDate(d: Date): string {
|
||||
return d.toLocaleDateString("en-US", {
|
||||
export function formatDate(d: Date, locale = "en-US"): string {
|
||||
return d.toLocaleDateString(locale, {
|
||||
year: "numeric",
|
||||
month: "short",
|
||||
day: "2-digit",
|
||||
})
|
||||
}
|
||||
|
||||
export function Date({ date }: Props) {
|
||||
return <>{formatDate(date)}</>
|
||||
export function Date({ date, locale }: Props) {
|
||||
return <>{formatDate(date, locale)}</>
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import explorerStyle from "./styles/explorer.scss"
|
||||
import script from "./scripts/explorer.inline"
|
||||
import { ExplorerNode, FileNode, Options } from "./ExplorerNode"
|
||||
import { QuartzPluginData } from "../plugins/vfile"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
// Options interface defined in `ExplorerNode` to avoid circular dependency
|
||||
const defaultOptions = {
|
||||
@ -69,16 +70,15 @@ export default ((userOpts?: Partial<Options>) => {
|
||||
}
|
||||
|
||||
// Get all folders of tree. Initialize with collapsed state
|
||||
const folders = fileTree.getFolderPaths(opts.folderDefaultState === "collapsed")
|
||||
|
||||
// Stringify to pass json tree as data attribute ([data-tree])
|
||||
const folders = fileTree.getFolderPaths(opts.folderDefaultState === "collapsed")
|
||||
jsonTree = JSON.stringify(folders)
|
||||
}
|
||||
|
||||
function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
|
||||
constructFileTree(allFiles)
|
||||
return (
|
||||
<div class={`explorer ${displayClass ?? ""}`}>
|
||||
<div class={classNames(displayClass, "explorer")}>
|
||||
<button
|
||||
type="button"
|
||||
id="explorer"
|
||||
|
||||
@ -2,6 +2,7 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
// @ts-ignore
|
||||
import script from "./scripts/graph.inline"
|
||||
import style from "./styles/graph.scss"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
export interface D3Config {
|
||||
drag: boolean
|
||||
@ -56,7 +57,7 @@ export default ((opts?: GraphOptions) => {
|
||||
const localGraph = { ...defaultOptions.localGraph, ...opts?.localGraph }
|
||||
const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph }
|
||||
return (
|
||||
<div class={`graph ${displayClass ?? ""}`}>
|
||||
<div class={classNames(displayClass, "graph")}>
|
||||
<h3>Graph View</h3>
|
||||
<div class="graph-outer">
|
||||
<div id="graph-container" data-cfg={JSON.stringify(localGraph)}></div>
|
||||
|
||||
@ -46,7 +46,7 @@ export function PageList({ cfg, fileData, allFiles, limit }: Props) {
|
||||
<div class="section">
|
||||
{page.dates && (
|
||||
<p class="meta">
|
||||
<Date date={getDate(cfg, page)!} />
|
||||
<Date date={getDate(cfg, page)!} locale={cfg.locale} />
|
||||
</p>
|
||||
)}
|
||||
<div class="desc">
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { pathToRoot } from "../util/path"
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
function PageTitle({ fileData, cfg, displayClass }: QuartzComponentProps) {
|
||||
const title = cfg?.pageTitle ?? "Untitled Quartz"
|
||||
const baseDir = pathToRoot(fileData.slug!)
|
||||
return (
|
||||
<h1 class={`page-title ${displayClass ?? ""}`}>
|
||||
<h1 class={classNames(displayClass, "page-title")}>
|
||||
<a href={baseDir}>{title}</a>
|
||||
</h1>
|
||||
)
|
||||
|
||||
@ -5,6 +5,7 @@ import { byDateAndAlphabetical } from "./PageList"
|
||||
import style from "./styles/recentNotes.scss"
|
||||
import { Date, getDate } from "./Date"
|
||||
import { GlobalConfiguration } from "../cfg"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
interface Options {
|
||||
title: string
|
||||
@ -28,7 +29,7 @@ export default ((userOpts?: Partial<Options>) => {
|
||||
const pages = allFiles.filter(opts.filter).sort(opts.sort)
|
||||
const remaining = Math.max(0, pages.length - opts.limit)
|
||||
return (
|
||||
<div class={`recent-notes ${displayClass ?? ""}`}>
|
||||
<div class={classNames(displayClass, "recent-notes")}>
|
||||
<h3>{opts.title}</h3>
|
||||
<ul class="recent-ul">
|
||||
{pages.slice(0, opts.limit).map((page) => {
|
||||
@ -47,7 +48,7 @@ export default ((userOpts?: Partial<Options>) => {
|
||||
</div>
|
||||
{page.dates && (
|
||||
<p class="meta">
|
||||
<Date date={getDate(cfg, page)!} />
|
||||
<Date date={getDate(cfg, page)!} locale={cfg.locale} />
|
||||
</p>
|
||||
)}
|
||||
<ul class="tags">
|
||||
|
||||
@ -2,11 +2,12 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import style from "./styles/search.scss"
|
||||
// @ts-ignore
|
||||
import script from "./scripts/search.inline"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
export default (() => {
|
||||
function Search({ displayClass }: QuartzComponentProps) {
|
||||
return (
|
||||
<div class={`search ${displayClass ?? ""}`}>
|
||||
<div class={classNames(displayClass, "search")}>
|
||||
<div id="search-icon">
|
||||
{/* <p>Search</p> */}
|
||||
<div></div>
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
function Spacer({ displayClass }: QuartzComponentProps) {
|
||||
return <div class={`spacer ${displayClass ?? ""}`}></div>
|
||||
return <div class={classNames(displayClass, "spacer")}></div>
|
||||
}
|
||||
|
||||
export default (() => Spacer) satisfies QuartzComponentConstructor
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import legacyStyle from "./styles/legacyToc.scss"
|
||||
import modernStyle from "./styles/toc.scss"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
// @ts-ignore
|
||||
import script from "./scripts/toc.inline"
|
||||
@ -19,7 +20,7 @@ function TableOfContents({ fileData, displayClass }: QuartzComponentProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div class={`toc ${displayClass ?? ""}`}>
|
||||
<div class={classNames(displayClass, "toc")}>
|
||||
<button type="button" id="toc" class={fileData.collapseToc ? "collapsed" : ""}>
|
||||
<h3>Table of Contents</h3>
|
||||
<svg
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { pathToRoot, slugTag } from "../util/path"
|
||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||
import { classNames } from "../util/lang"
|
||||
|
||||
function TagList({ fileData, displayClass }: QuartzComponentProps) {
|
||||
const tags = fileData.frontmatter?.tags
|
||||
const baseDir = pathToRoot(fileData.slug!)
|
||||
if (tags && tags.length > 0) {
|
||||
return (
|
||||
<ul class={`tags ${displayClass ?? ""}`}>
|
||||
<ul class={classNames(displayClass, "tags")}>
|
||||
{tags.map((tag) => {
|
||||
const display = `#${tag}`
|
||||
const linkDest = baseDir + `/tags/${slugTag(tag)}`
|
||||
|
||||
@ -33,7 +33,8 @@ export default ((opts?: Partial<FolderContentOptions>) => {
|
||||
const isDirectChild = fileParts.length === folderParts.length + 1
|
||||
return prefixed && isDirectChild
|
||||
})
|
||||
|
||||
const cssClasses: string[] = fileData.frontmatter?.cssclasses ?? []
|
||||
const classes = ["popover-hint", ...cssClasses].join(" ")
|
||||
const listProps = {
|
||||
...props,
|
||||
allFiles: allPagesInFolder,
|
||||
@ -45,15 +46,17 @@ export default ((opts?: Partial<FolderContentOptions>) => {
|
||||
: htmlToJsx(fileData.filePath!, tree)
|
||||
|
||||
return (
|
||||
<div class="popover-hint">
|
||||
<div class={classes}>
|
||||
<article>
|
||||
<p>{content}</p>
|
||||
</article>
|
||||
{options.showFolderCount && (
|
||||
<p>{pluralize(allPagesInFolder.length, "item")} under this folder.</p>
|
||||
)}
|
||||
<div>
|
||||
<PageList {...listProps} />
|
||||
<div class="page-listing">
|
||||
{options.showFolderCount && (
|
||||
<p>{pluralize(allPagesInFolder.length, "item")} under this folder.</p>
|
||||
)}
|
||||
<div>
|
||||
<PageList {...listProps} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -26,7 +26,8 @@ function TagContent(props: QuartzComponentProps) {
|
||||
(tree as Root).children.length === 0
|
||||
? fileData.description
|
||||
: htmlToJsx(fileData.filePath!, tree)
|
||||
|
||||
const cssClasses: string[] = fileData.frontmatter?.cssclasses ?? []
|
||||
const classes = ["popover-hint", ...cssClasses].join(" ")
|
||||
if (tag === "/") {
|
||||
const tags = [
|
||||
...new Set(
|
||||
@ -37,9 +38,8 @@ function TagContent(props: QuartzComponentProps) {
|
||||
for (const tag of tags) {
|
||||
tagItemMap.set(tag, allPagesWithTag(tag))
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="popover-hint">
|
||||
<div class={classes}>
|
||||
<article>
|
||||
<p>{content}</p>
|
||||
</article>
|
||||
@ -62,11 +62,13 @@ function TagContent(props: QuartzComponentProps) {
|
||||
</a>
|
||||
</h2>
|
||||
{content && <p>{content}</p>}
|
||||
<p>
|
||||
{pluralize(pages.length, "item")} with this tag.{" "}
|
||||
{pages.length > numPages && `Showing first ${numPages}.`}
|
||||
</p>
|
||||
<PageList limit={numPages} {...listProps} />
|
||||
<div class="page-listing">
|
||||
<p>
|
||||
{pluralize(pages.length, "item")} with this tag.{" "}
|
||||
{pages.length > numPages && `Showing first ${numPages}.`}
|
||||
</p>
|
||||
<PageList limit={numPages} {...listProps} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@ -81,11 +83,13 @@ function TagContent(props: QuartzComponentProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="popover-hint">
|
||||
<div class={classes}>
|
||||
<article>{content}</article>
|
||||
<p>{pluralize(pages.length, "item")} with this tag.</p>
|
||||
<div>
|
||||
<PageList {...listProps} />
|
||||
<div class="page-listing">
|
||||
<p>{pluralize(pages.length, "item")} with this tag.</p>
|
||||
<div>
|
||||
<PageList {...listProps} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -1,132 +1,106 @@
|
||||
import { FolderState } from "../ExplorerNode"
|
||||
|
||||
// Current state of folders
|
||||
let explorerState: FolderState[]
|
||||
|
||||
type MaybeHTMLElement = HTMLElement | undefined
|
||||
let currentExplorerState: FolderState[]
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
// If last element is observed, remove gradient of "overflow" class so element is visible
|
||||
const explorer = document.getElementById("explorer-ul")
|
||||
const explorerUl = document.getElementById("explorer-ul")
|
||||
if (!explorerUl) return
|
||||
for (const entry of entries) {
|
||||
if (entry.isIntersecting) {
|
||||
explorer?.classList.add("no-background")
|
||||
explorerUl.classList.add("no-background")
|
||||
} else {
|
||||
explorer?.classList.remove("no-background")
|
||||
explorerUl.classList.remove("no-background")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function toggleExplorer(this: HTMLElement) {
|
||||
// Toggle collapsed state of entire explorer
|
||||
this.classList.toggle("collapsed")
|
||||
const content = this.nextElementSibling as HTMLElement
|
||||
const content = this.nextElementSibling as MaybeHTMLElement
|
||||
if (!content) return
|
||||
|
||||
content.classList.toggle("collapsed")
|
||||
content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px"
|
||||
}
|
||||
|
||||
function toggleFolder(evt: MouseEvent) {
|
||||
evt.stopPropagation()
|
||||
const target = evt.target as MaybeHTMLElement
|
||||
if (!target) return
|
||||
|
||||
// Element that was clicked
|
||||
const target = evt.target as HTMLElement
|
||||
|
||||
// Check if target was svg icon or button
|
||||
const isSvg = target.nodeName === "svg"
|
||||
const childFolderContainer = (
|
||||
isSvg
|
||||
? target.parentElement?.nextSibling
|
||||
: target.parentElement?.parentElement?.nextElementSibling
|
||||
) as MaybeHTMLElement
|
||||
const currentFolderParent = (
|
||||
isSvg ? target.nextElementSibling : target.parentElement
|
||||
) as MaybeHTMLElement
|
||||
if (!(childFolderContainer && currentFolderParent)) return
|
||||
|
||||
// corresponding <ul> element relative to clicked button/folder
|
||||
let childFolderContainer: HTMLElement
|
||||
|
||||
// <li> element of folder (stores folder-path dataset)
|
||||
let currentFolderParent: HTMLElement
|
||||
|
||||
// Get correct relative container and toggle collapsed class
|
||||
if (isSvg) {
|
||||
childFolderContainer = target.parentElement?.nextSibling as HTMLElement
|
||||
currentFolderParent = target.nextElementSibling as HTMLElement
|
||||
|
||||
childFolderContainer.classList.toggle("open")
|
||||
} else {
|
||||
childFolderContainer = target.parentElement?.parentElement?.nextElementSibling as HTMLElement
|
||||
currentFolderParent = target.parentElement as HTMLElement
|
||||
|
||||
childFolderContainer.classList.toggle("open")
|
||||
}
|
||||
if (!childFolderContainer) return
|
||||
|
||||
// Collapse folder container
|
||||
childFolderContainer.classList.toggle("open")
|
||||
const isCollapsed = childFolderContainer.classList.contains("open")
|
||||
setFolderState(childFolderContainer, !isCollapsed)
|
||||
|
||||
// Save folder state to localStorage
|
||||
const clickFolderPath = currentFolderParent.dataset.folderpath as string
|
||||
|
||||
const fullFolderPath = clickFolderPath
|
||||
toggleCollapsedByPath(explorerState, fullFolderPath)
|
||||
|
||||
const stringifiedFileTree = JSON.stringify(explorerState)
|
||||
const fullFolderPath = currentFolderParent.dataset.folderpath as string
|
||||
toggleCollapsedByPath(currentExplorerState, fullFolderPath)
|
||||
const stringifiedFileTree = JSON.stringify(currentExplorerState)
|
||||
localStorage.setItem("fileTree", stringifiedFileTree)
|
||||
}
|
||||
|
||||
function setupExplorer() {
|
||||
// Set click handler for collapsing entire explorer
|
||||
const explorer = document.getElementById("explorer")
|
||||
if (!explorer) return
|
||||
|
||||
if (explorer.dataset.behavior === "collapse") {
|
||||
for (const item of document.getElementsByClassName(
|
||||
"folder-button",
|
||||
) as HTMLCollectionOf<HTMLElement>) {
|
||||
item.removeEventListener("click", toggleFolder)
|
||||
item.addEventListener("click", toggleFolder)
|
||||
}
|
||||
}
|
||||
|
||||
explorer.removeEventListener("click", toggleExplorer)
|
||||
explorer.addEventListener("click", toggleExplorer)
|
||||
|
||||
// Set up click handlers for each folder (click handler on folder "icon")
|
||||
for (const item of document.getElementsByClassName(
|
||||
"folder-icon",
|
||||
) as HTMLCollectionOf<HTMLElement>) {
|
||||
item.removeEventListener("click", toggleFolder)
|
||||
item.addEventListener("click", toggleFolder)
|
||||
}
|
||||
|
||||
// Get folder state from local storage
|
||||
const storageTree = localStorage.getItem("fileTree")
|
||||
|
||||
// Convert to bool
|
||||
const useSavedFolderState = explorer?.dataset.savestate === "true"
|
||||
const oldExplorerState: FolderState[] =
|
||||
storageTree && useSavedFolderState ? JSON.parse(storageTree) : []
|
||||
const oldIndex = new Map(oldExplorerState.map((entry) => [entry.path, entry.collapsed]))
|
||||
const newExplorerState: FolderState[] = explorer.dataset.tree
|
||||
? JSON.parse(explorer.dataset.tree)
|
||||
: []
|
||||
currentExplorerState = []
|
||||
for (const { path, collapsed } of newExplorerState) {
|
||||
currentExplorerState.push({ path, collapsed: oldIndex.get(path) ?? collapsed })
|
||||
}
|
||||
|
||||
if (explorer) {
|
||||
// Get config
|
||||
const collapseBehavior = explorer.dataset.behavior
|
||||
|
||||
// Add click handlers for all folders (click handler on folder "label")
|
||||
if (collapseBehavior === "collapse") {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName("folder-button"),
|
||||
function (item) {
|
||||
item.removeEventListener("click", toggleFolder)
|
||||
item.addEventListener("click", toggleFolder)
|
||||
},
|
||||
)
|
||||
currentExplorerState.map((folderState) => {
|
||||
const folderLi = document.querySelector(
|
||||
`[data-folderpath='${folderState.path}']`,
|
||||
) as MaybeHTMLElement
|
||||
const folderUl = folderLi?.parentElement?.nextElementSibling as MaybeHTMLElement
|
||||
if (folderUl) {
|
||||
setFolderState(folderUl, folderState.collapsed)
|
||||
}
|
||||
|
||||
// Add click handler to main explorer
|
||||
explorer.removeEventListener("click", toggleExplorer)
|
||||
explorer.addEventListener("click", toggleExplorer)
|
||||
}
|
||||
|
||||
// Set up click handlers for each folder (click handler on folder "icon")
|
||||
Array.prototype.forEach.call(document.getElementsByClassName("folder-icon"), function (item) {
|
||||
item.removeEventListener("click", toggleFolder)
|
||||
item.addEventListener("click", toggleFolder)
|
||||
})
|
||||
|
||||
if (storageTree && useSavedFolderState) {
|
||||
// Get state from localStorage and set folder state
|
||||
explorerState = JSON.parse(storageTree)
|
||||
explorerState.map((folderUl) => {
|
||||
// grab <li> element for matching folder path
|
||||
const folderLi = document.querySelector(`[data-folderpath='${folderUl.path}']`) as HTMLElement
|
||||
|
||||
// Get corresponding content <ul> tag and set state
|
||||
if (folderLi) {
|
||||
const folderUL = folderLi.parentElement?.nextElementSibling
|
||||
if (folderUL) {
|
||||
setFolderState(folderUL as HTMLElement, folderUl.collapsed)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if (explorer?.dataset.tree) {
|
||||
// If tree is not in localStorage or config is disabled, use tree passed from Explorer as dataset
|
||||
explorerState = JSON.parse(explorer.dataset.tree)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("resize", setupExplorer)
|
||||
document.addEventListener("nav", () => {
|
||||
setupExplorer()
|
||||
|
||||
observer.disconnect()
|
||||
|
||||
// select pseudo element at end of list
|
||||
@ -142,11 +116,7 @@ document.addEventListener("nav", () => {
|
||||
* @param collapsed if folder should be set to collapsed or not
|
||||
*/
|
||||
function setFolderState(folderElement: HTMLElement, collapsed: boolean) {
|
||||
if (collapsed) {
|
||||
folderElement?.classList.remove("open")
|
||||
} else {
|
||||
folderElement?.classList.add("open")
|
||||
}
|
||||
return collapsed ? folderElement.classList.remove("open") : folderElement.classList.add("open")
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -319,8 +319,8 @@ function renderGlobalGraph() {
|
||||
registerEscapeHandler(container, hideGlobalGraph)
|
||||
}
|
||||
|
||||
document.addEventListener("nav", async (e: unknown) => {
|
||||
const slug = (e as CustomEventMap["nav"]).detail.url
|
||||
document.addEventListener("nav", async (e: CustomEventMap["nav"]) => {
|
||||
const slug = e.detail.url
|
||||
addToVisited(slug)
|
||||
await renderGraph("graph-container", slug)
|
||||
|
||||
|
||||
@ -16,7 +16,8 @@ const observer = new IntersectionObserver((entries) => {
|
||||
|
||||
function toggleToc(this: HTMLElement) {
|
||||
this.classList.toggle("collapsed")
|
||||
const content = this.nextElementSibling as 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"
|
||||
}
|
||||
@ -25,7 +26,8 @@ function setupToc() {
|
||||
const toc = document.getElementById("toc")
|
||||
if (toc) {
|
||||
const collapsed = toc.classList.contains("collapsed")
|
||||
const content = toc.nextElementSibling as HTMLElement
|
||||
const content = toc.nextElementSibling as HTMLElement | undefined
|
||||
if (!content) return
|
||||
content.style.maxHeight = collapsed ? "0px" : content.scrollHeight + "px"
|
||||
toc.removeEventListener("click", toggleToc)
|
||||
toc.addEventListener("click", toggleToc)
|
||||
|
||||
@ -119,7 +119,7 @@ function addGlobalPageResources(
|
||||
} else if (cfg.analytics?.provider === "umami") {
|
||||
componentResources.afterDOMLoaded.push(`
|
||||
const umamiScript = document.createElement("script")
|
||||
umamiScript.src = "https://analytics.umami.is/script.js"
|
||||
umamiScript.src = cfg.analytics.host ?? "https://analytics.umami.is/script.js"
|
||||
umamiScript.setAttribute("data-website-id", "${cfg.analytics.websiteId}")
|
||||
umamiScript.async = true
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import yaml from "js-yaml"
|
||||
import toml from "toml"
|
||||
import { slugTag } from "../../util/path"
|
||||
import { QuartzPluginData } from "../vfile"
|
||||
import chalk from "chalk"
|
||||
|
||||
export interface Options {
|
||||
delims: string | string[]
|
||||
@ -17,23 +16,6 @@ const defaultOptions: Options = {
|
||||
language: "yaml",
|
||||
}
|
||||
|
||||
function coerceDate(fp: string, d: unknown): Date | undefined {
|
||||
if (d === undefined || d === null) return undefined
|
||||
const dt = new Date(d as string | number)
|
||||
const invalidDate = isNaN(dt.getTime()) || dt.getTime() === 0
|
||||
if (invalidDate) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
`\nWarning: found invalid date "${d}" in \`${fp}\`. Supported formats: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format`,
|
||||
),
|
||||
)
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
return dt
|
||||
}
|
||||
|
||||
function coalesceAliases(data: { [key: string]: any }, aliases: string[]) {
|
||||
for (const alias of aliases) {
|
||||
if (data[alias] !== undefined && data[alias] !== null) return data[alias]
|
||||
@ -66,7 +48,6 @@ export const FrontMatter: QuartzTransformerPlugin<Partial<Options> | undefined>
|
||||
[remarkFrontmatter, ["yaml", "toml"]],
|
||||
() => {
|
||||
return (_, file) => {
|
||||
const fp = file.data.filePath!
|
||||
const { data } = matter(Buffer.from(file.value), {
|
||||
...opts,
|
||||
engines: {
|
||||
@ -88,16 +69,6 @@ export const FrontMatter: QuartzTransformerPlugin<Partial<Options> | undefined>
|
||||
if (aliases) data.aliases = aliases
|
||||
const cssclasses = coerceToArray(coalesceAliases(data, ["cssclasses", "cssclass"]))
|
||||
if (cssclasses) data.cssclasses = cssclasses
|
||||
const created = coerceDate(fp, coalesceAliases(data, ["created", "date"]))
|
||||
|
||||
if (created) data.created = created
|
||||
const modified = coerceDate(
|
||||
fp,
|
||||
coalesceAliases(data, ["modified", "lastmod", "updated", "last-modified"]),
|
||||
)
|
||||
if (modified) data.modified = modified
|
||||
const published = coerceDate(fp, coalesceAliases(data, ["published", "publishDate"]))
|
||||
if (published) data.published = published
|
||||
|
||||
// fill in frontmatter
|
||||
file.data.frontmatter = data as QuartzPluginData["frontmatter"]
|
||||
@ -120,9 +91,6 @@ declare module "vfile" {
|
||||
draft: boolean
|
||||
enableToc: string
|
||||
cssclasses: string[]
|
||||
created: Date
|
||||
modified: Date
|
||||
published: Date
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,8 +37,36 @@ export const GitHubFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options> |
|
||||
"data-no-popover": true,
|
||||
},
|
||||
content: {
|
||||
type: "text",
|
||||
value: " §",
|
||||
type: "element",
|
||||
tagName: "svg",
|
||||
properties: {
|
||||
width: 18,
|
||||
height: 18,
|
||||
viewBox: "0 0 24 24",
|
||||
fill: "none",
|
||||
stroke: "currentColor",
|
||||
"stroke-width": "2",
|
||||
"stroke-linecap": "round",
|
||||
"stroke-linejoin": "round",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: "element",
|
||||
tagName: "path",
|
||||
properties: {
|
||||
d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71",
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
type: "element",
|
||||
tagName: "path",
|
||||
properties: {
|
||||
d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71",
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -12,6 +12,21 @@ const defaultOptions: Options = {
|
||||
priority: ["frontmatter", "git", "filesystem"],
|
||||
}
|
||||
|
||||
function coerceDate(fp: string, d: any): Date {
|
||||
const dt = new Date(d)
|
||||
const invalidDate = isNaN(dt.getTime()) || dt.getTime() === 0
|
||||
if (invalidDate && d !== undefined) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
`\nWarning: found invalid date "${d}" in \`${fp}\`. Supported formats: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format`,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return invalidDate ? new Date() : dt
|
||||
}
|
||||
|
||||
type MaybeDate = undefined | string | number
|
||||
export const CreatedModifiedDate: QuartzTransformerPlugin<Partial<Options> | undefined> = (
|
||||
userOpts,
|
||||
) => {
|
||||
@ -23,21 +38,23 @@ export const CreatedModifiedDate: QuartzTransformerPlugin<Partial<Options> | und
|
||||
() => {
|
||||
let repo: Repository | undefined = undefined
|
||||
return async (_tree, file) => {
|
||||
let created: Date | undefined = undefined
|
||||
let modified: Date | undefined = undefined
|
||||
let published: Date | undefined = undefined
|
||||
let created: MaybeDate = undefined
|
||||
let modified: MaybeDate = undefined
|
||||
let published: MaybeDate = undefined
|
||||
|
||||
const fp = file.data.filePath!
|
||||
const fullFp = path.posix.join(file.cwd, fp)
|
||||
for (const source of opts.priority) {
|
||||
if (source === "filesystem") {
|
||||
const st = await fs.promises.stat(fullFp)
|
||||
created ||= new Date(st.birthtimeMs)
|
||||
modified ||= new Date(st.mtimeMs)
|
||||
created ||= st.birthtimeMs
|
||||
modified ||= st.mtimeMs
|
||||
} else if (source === "frontmatter" && file.data.frontmatter) {
|
||||
created ||= file.data.frontmatter.created
|
||||
modified ||= file.data.frontmatter.modified
|
||||
published ||= file.data.frontmatter.published
|
||||
created ||= file.data.frontmatter.date as MaybeDate
|
||||
modified ||= file.data.frontmatter.lastmod as MaybeDate
|
||||
modified ||= file.data.frontmatter.updated as MaybeDate
|
||||
modified ||= file.data.frontmatter["last-modified"] as MaybeDate
|
||||
published ||= file.data.frontmatter.publishDate as MaybeDate
|
||||
} else if (source === "git") {
|
||||
if (!repo) {
|
||||
// Get a reference to the main git repo.
|
||||
@ -47,9 +64,7 @@ export const CreatedModifiedDate: QuartzTransformerPlugin<Partial<Options> | und
|
||||
}
|
||||
|
||||
try {
|
||||
modified ||= new Date(
|
||||
await repo.getFileLatestModifiedDateAsync(file.data.filePath!),
|
||||
)
|
||||
modified ||= await repo.getFileLatestModifiedDateAsync(file.data.filePath!)
|
||||
} catch {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
@ -61,13 +76,10 @@ export const CreatedModifiedDate: QuartzTransformerPlugin<Partial<Options> | und
|
||||
}
|
||||
}
|
||||
|
||||
created ||= new Date()
|
||||
modified ||= new Date()
|
||||
published ||= new Date()
|
||||
file.data.dates = {
|
||||
created,
|
||||
modified,
|
||||
published,
|
||||
created: coerceDate(fp, created),
|
||||
modified: coerceDate(fp, modified),
|
||||
published: coerceDate(fp, published),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -138,6 +138,9 @@ const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\p{Emoji}\d])+(?:\/[-_\p{L}\p{E
|
||||
const blockReferenceRegex = new RegExp(/\^([-_A-Za-z0-9]+)$/, "g")
|
||||
const ytLinkRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
|
||||
const videoExtensionRegex = new RegExp(/\.(mp4|webm|ogg|avi|mov|flv|wmv|mkv|mpg|mpeg|3gp|m4v)$/)
|
||||
const wikilinkImageEmbedRegex = new RegExp(
|
||||
/^(?<alt>(?!^\d*x?\d*$).*?)?(\|?\s*?(?<width>\d+)(x(?<height>\d+))?)?$/,
|
||||
)
|
||||
|
||||
export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options> | undefined> = (
|
||||
userOpts,
|
||||
@ -222,18 +225,10 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
|
||||
const ext: string = path.extname(fp).toLowerCase()
|
||||
const url = slugifyFilePath(fp as FilePath)
|
||||
if ([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg", ".webp"].includes(ext)) {
|
||||
// either |alt|dims or |dims
|
||||
let [alt, dims] = (alias ?? "").split("|")
|
||||
|
||||
// |dims case, treat first alt slot as dims
|
||||
if (dims === undefined) {
|
||||
dims = alt
|
||||
alt = ""
|
||||
}
|
||||
|
||||
let [width, height] = dims.split("x", 2)
|
||||
width ||= "auto"
|
||||
height ||= "auto"
|
||||
const match = wikilinkImageEmbedRegex.exec(alias ?? "")
|
||||
const alt = match?.groups?.alt ?? ""
|
||||
const width = match?.groups?.width ?? "auto"
|
||||
const height = match?.groups?.height ?? "auto"
|
||||
return {
|
||||
type: "image",
|
||||
url,
|
||||
@ -441,7 +436,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
|
||||
value: `<div
|
||||
class="callout-title"
|
||||
>
|
||||
<div class="callout-icon">${callouts[calloutType] ?? callouts.note}</div>
|
||||
<div class="callout-icon">${callouts[calloutType] ?? callouts.note}</div>
|
||||
<div class="callout-title-inner">${title}</div>
|
||||
${collapse ? toggleIcon : ""}
|
||||
</div>`,
|
||||
|
||||
@ -175,9 +175,11 @@ a {
|
||||
|
||||
& .sidebar.right {
|
||||
right: calc(calc(100vw - $pageWidth) / 2 - $sidePanelWidth);
|
||||
flex-wrap: wrap;
|
||||
& > * {
|
||||
@media all and (max-width: $fullPageWidth) {
|
||||
flex: 1;
|
||||
min-width: 140px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -280,7 +282,6 @@ h6 {
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
transform: translateY(-0.1rem);
|
||||
display: inline-block;
|
||||
font-family: var(--codeFont);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@ -9,3 +9,13 @@ export function pluralize(count: number, s: string): string {
|
||||
export function capitalize(s: string): string {
|
||||
return s.substring(0, 1).toUpperCase() + s.substring(1)
|
||||
}
|
||||
|
||||
export function classNames(
|
||||
displayClass?: "mobile-only" | "desktop-only",
|
||||
...classes: string[]
|
||||
): string {
|
||||
if (displayClass) {
|
||||
classes.push(displayClass)
|
||||
}
|
||||
return classes.join(" ")
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ function sluggify(s: string): string {
|
||||
.split("/")
|
||||
.map((segment) =>
|
||||
segment.replace(/\s/g, "-").replace(/%/g, "-percent").replace(/\?/g, "-q").replace(/#/g, ""),
|
||||
) // slugify all segments
|
||||
)
|
||||
.join("/") // always use / as sep
|
||||
.replace(/\/$/, "")
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user