Build stamp, live listening strip, OG cards, closer shiki ground
- footer: 'built <ts> · <hash> · <n> notes', hash linking to Gitea (GARDEN_COMMIT passed in by build.sh; '+' marks dirty-tree builds) - homepage header: live strip fed by api.c0smere.net/spotify/summary (weekly aggregate + monthly top artist/genre), fail-closed like the odometer and header quote - /og/<slug>.png satori+resvg cards for every note + the homepage; og:/twitter: meta in Base - shiki github-dark-default (#0d1117 sits closer to the page ground) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -13,7 +13,8 @@ export default defineConfig({
|
||||
markdown: {
|
||||
remarkPlugins: [[remarkObsidian, { slugMap }], remarkMath],
|
||||
rehypePlugins: [rehypeKatex],
|
||||
// single dark theme — the site is fixed-dark to match blog.c0smere.net
|
||||
shikiConfig: { theme: 'github-dark' },
|
||||
// single dark theme — the site is fixed-dark to match blog.c0smere.net;
|
||||
// -default variant's #0d1117 ground sits closer to the page's #0b0d12
|
||||
shikiConfig: { theme: 'github-dark-default' },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -5,6 +5,13 @@ set -eu
|
||||
|
||||
VAULT="${VAULT:-/home/nox/docker/obsidian/vaults/weeslahw_coppermind}"
|
||||
|
||||
# footer build stamp: the node container has no git, so resolve the
|
||||
# commit here ("+" = dirty tree, e.g. a local-state build after a failed pull)
|
||||
COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo '')
|
||||
if [ -n "$COMMIT" ] && ! git diff --quiet 2>/dev/null; then
|
||||
COMMIT="${COMMIT}+"
|
||||
fi
|
||||
|
||||
# --user: build artifacts (node_modules, dist, public/assets) must stay
|
||||
# owned by the invoking user, or the next git pull can't write the tree
|
||||
docker run --rm \
|
||||
@@ -12,6 +19,7 @@ docker run --rm \
|
||||
-v "$(pwd):/app" \
|
||||
-v "$VAULT:/content:ro" \
|
||||
-e GARDEN_CONTENT=/content/Digital_Garden \
|
||||
-e GARDEN_COMMIT="$COMMIT" \
|
||||
-e ASTRO_TELEMETRY_DISABLED=1 \
|
||||
-e HOME=/tmp \
|
||||
-e npm_config_cache=/tmp/.npm \
|
||||
|
||||
Generated
+429
@@ -8,12 +8,15 @@
|
||||
"name": "garden-astro",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@fontsource/jetbrains-mono": "^5.3.0",
|
||||
"@resvg/resvg-js": "^2.6.2",
|
||||
"astro": "^5.0.0",
|
||||
"github-slugger": "^2.0.0",
|
||||
"katex": "^0.16.10",
|
||||
"mermaid": "^11.0.0",
|
||||
"rehype-katex": "^7.0.0",
|
||||
"remark-math": "^6.0.0",
|
||||
"satori": "^0.28.2",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
}
|
||||
},
|
||||
@@ -597,6 +600,15 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/jetbrains-mono": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/jetbrains-mono/-/jetbrains-mono-5.3.0.tgz",
|
||||
"integrity": "sha512-fqDfB5I9f1p1TV486aUgB9t8zP84P0O1FtQR5Ol9vjwPy+S+EIGlVYm1cvj2W5shcZMTg2nZFdVMoH5wFu8a1A==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"node_modules/@iconify/types": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
|
||||
@@ -1149,6 +1161,233 @@
|
||||
"integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@resvg/resvg-js": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js/-/resvg-js-2.6.2.tgz",
|
||||
"integrity": "sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==",
|
||||
"license": "MPL-2.0",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@resvg/resvg-js-android-arm-eabi": "2.6.2",
|
||||
"@resvg/resvg-js-android-arm64": "2.6.2",
|
||||
"@resvg/resvg-js-darwin-arm64": "2.6.2",
|
||||
"@resvg/resvg-js-darwin-x64": "2.6.2",
|
||||
"@resvg/resvg-js-linux-arm-gnueabihf": "2.6.2",
|
||||
"@resvg/resvg-js-linux-arm64-gnu": "2.6.2",
|
||||
"@resvg/resvg-js-linux-arm64-musl": "2.6.2",
|
||||
"@resvg/resvg-js-linux-x64-gnu": "2.6.2",
|
||||
"@resvg/resvg-js-linux-x64-musl": "2.6.2",
|
||||
"@resvg/resvg-js-win32-arm64-msvc": "2.6.2",
|
||||
"@resvg/resvg-js-win32-ia32-msvc": "2.6.2",
|
||||
"@resvg/resvg-js-win32-x64-msvc": "2.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-android-arm-eabi": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm-eabi/-/resvg-js-android-arm-eabi-2.6.2.tgz",
|
||||
"integrity": "sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-android-arm64": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm64/-/resvg-js-android-arm64-2.6.2.tgz",
|
||||
"integrity": "sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-darwin-arm64": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-arm64/-/resvg-js-darwin-arm64-2.6.2.tgz",
|
||||
"integrity": "sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-darwin-x64": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-x64/-/resvg-js-darwin-x64-2.6.2.tgz",
|
||||
"integrity": "sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-linux-arm-gnueabihf": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm-gnueabihf/-/resvg-js-linux-arm-gnueabihf-2.6.2.tgz",
|
||||
"integrity": "sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-linux-arm64-gnu": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-gnu/-/resvg-js-linux-arm64-gnu-2.6.2.tgz",
|
||||
"integrity": "sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-linux-arm64-musl": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-musl/-/resvg-js-linux-arm64-musl-2.6.2.tgz",
|
||||
"integrity": "sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-linux-x64-gnu": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-gnu/-/resvg-js-linux-x64-gnu-2.6.2.tgz",
|
||||
"integrity": "sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-linux-x64-musl": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-musl/-/resvg-js-linux-x64-musl-2.6.2.tgz",
|
||||
"integrity": "sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-win32-arm64-msvc": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-arm64-msvc/-/resvg-js-win32-arm64-msvc-2.6.2.tgz",
|
||||
"integrity": "sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-win32-ia32-msvc": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-ia32-msvc/-/resvg-js-win32-ia32-msvc-2.6.2.tgz",
|
||||
"integrity": "sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@resvg/resvg-js-win32-x64-msvc": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-x64-msvc/-/resvg-js-win32-x64-msvc-2.6.2.tgz",
|
||||
"integrity": "sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz",
|
||||
@@ -1608,6 +1847,22 @@
|
||||
"integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@shuding/opentype.js": {
|
||||
"version": "1.4.0-beta.0",
|
||||
"resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz",
|
||||
"integrity": "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fflate": "^0.7.3",
|
||||
"string.prototype.codepointat": "^0.2.1"
|
||||
},
|
||||
"bin": {
|
||||
"ot": "bin/ot"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/d3": {
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz",
|
||||
@@ -2197,6 +2452,15 @@
|
||||
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
|
||||
"integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
@@ -2237,6 +2501,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/camelize": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
|
||||
"integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/ccount": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
|
||||
@@ -2340,6 +2613,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/comma-separated-tokens": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
|
||||
@@ -2402,6 +2681,36 @@
|
||||
"uncrypto": "^0.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/css-background-parser": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz",
|
||||
"integrity": "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/css-box-shadow": {
|
||||
"version": "1.0.0-3",
|
||||
"resolved": "https://registry.npmjs.org/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz",
|
||||
"integrity": "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/css-color-keywords": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
|
||||
"integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/css-gradient-parser": {
|
||||
"version": "0.0.17",
|
||||
"resolved": "https://registry.npmjs.org/css-gradient-parser/-/css-gradient-parser-0.0.17.tgz",
|
||||
"integrity": "sha512-w2Xy9UMMwlKtou0vlRnXvWglPAceXCTtcmVSo8ZBUvqCV5aXEFP/PC6d+I464810I9FT++UACwTD5511bmGPUg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
|
||||
@@ -2418,6 +2727,17 @@
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/css-to-react-native": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
|
||||
"integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"camelize": "^1.0.0",
|
||||
"css-color-keywords": "^1.0.0",
|
||||
"postcss-value-parser": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/css-tree": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
|
||||
@@ -3209,6 +3529,15 @@
|
||||
"integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/emoji-regex-xs": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-2.0.1.tgz",
|
||||
"integrity": "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
||||
@@ -3278,6 +3607,12 @@
|
||||
"@esbuild/win32-x64": "0.27.7"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||
@@ -3328,6 +3663,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fflate": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.5.tgz",
|
||||
"integrity": "sha512-QieYf//cis6ywHNi5qW1+PXPQ4bC+XVJAtS4AXIML8P76GroEiOxm/oQtn1f02UkJY1+KsXMJcC+R2v/Eg4G3g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/flattie": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz",
|
||||
@@ -3621,6 +3962,18 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/hex-rgb": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-4.3.0.tgz",
|
||||
"integrity": "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
|
||||
@@ -3810,6 +4163,16 @@
|
||||
"integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/linebreak": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
|
||||
"integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "0.0.8",
|
||||
"unicode-trie": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.18.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
|
||||
@@ -4909,6 +5272,22 @@
|
||||
"integrity": "sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
|
||||
"integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/parse-css-color": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-css-color/-/parse-css-color-0.2.1.tgz",
|
||||
"integrity": "sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "^1.1.4",
|
||||
"hex-rgb": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-latin": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz",
|
||||
@@ -5013,6 +5392,12 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-value-parser": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prismjs": {
|
||||
"version": "1.30.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
|
||||
@@ -5400,6 +5785,28 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/satori": {
|
||||
"version": "0.28.2",
|
||||
"resolved": "https://registry.npmjs.org/satori/-/satori-0.28.2.tgz",
|
||||
"integrity": "sha512-AZBuptlBvlMf+EC/WI6Ss5MJwSEstrC6Pf1o5b2keg6h1QbvjStmrnJXUDGWOrfC1KSU0FApyGhF2xnBwmJRgA==",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"@shuding/opentype.js": "1.4.0-beta.0",
|
||||
"css-background-parser": "^0.1.0",
|
||||
"css-box-shadow": "1.0.0-3",
|
||||
"css-gradient-parser": "^0.0.17",
|
||||
"css-to-react-native": "^3.0.0",
|
||||
"emoji-regex-xs": "^2.0.1",
|
||||
"escape-html": "^1.0.3",
|
||||
"linebreak": "^1.1.0",
|
||||
"parse-css-color": "^0.2.1",
|
||||
"postcss-value-parser": "^4.2.0",
|
||||
"yoga-layout": "^3.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
|
||||
@@ -5536,6 +5943,12 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/string.prototype.codepointat": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
|
||||
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stringify-entities": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
|
||||
@@ -5737,6 +6150,16 @@
|
||||
"integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unicode-trie": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
|
||||
"integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pako": "^0.2.5",
|
||||
"tiny-inflate": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unified": {
|
||||
"version": "11.0.5",
|
||||
"resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
|
||||
@@ -6696,6 +7119,12 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/yoga-layout": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz",
|
||||
"integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.25.76",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
|
||||
@@ -9,12 +9,15 @@
|
||||
"preview": "astro preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/jetbrains-mono": "^5.3.0",
|
||||
"@resvg/resvg-js": "^2.6.2",
|
||||
"astro": "^5.0.0",
|
||||
"github-slugger": "^2.0.0",
|
||||
"katex": "^0.16.10",
|
||||
"mermaid": "^11.0.0",
|
||||
"rehype-katex": "^7.0.0",
|
||||
"remark-math": "^6.0.0",
|
||||
"satori": "^0.28.2",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"allowScripts": {
|
||||
|
||||
+115
-2
@@ -2,6 +2,7 @@
|
||||
import 'katex/dist/katex.min.css';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { buildNavTree } from '../lib/nav.mjs';
|
||||
import { COMMIT, BUILT_AT } from '../lib/build-info.mjs';
|
||||
import NavTree from '../components/NavTree.astro';
|
||||
import Toc from '../components/Toc.astro';
|
||||
|
||||
@@ -9,11 +10,18 @@ interface Props {
|
||||
title: string;
|
||||
description?: string;
|
||||
headings?: { depth: number; slug: string; text: string }[];
|
||||
// which /og/<slug>.png card this page advertises; synthetic listing
|
||||
// pages fall back to the site card
|
||||
ogSlug?: string;
|
||||
}
|
||||
const { title, description, headings = [] } = Astro.props;
|
||||
const { title, description, headings = [], ogSlug = 'index' } = Astro.props;
|
||||
const isHome = Astro.url.pathname === '/';
|
||||
const navTree = buildNavTree(await getCollection('garden'));
|
||||
const entries = await getCollection('garden');
|
||||
const navTree = buildNavTree(entries);
|
||||
const noteCount = entries.length;
|
||||
const showToc = headings.filter((h) => h.depth <= 3).length >= 2;
|
||||
const ogImage = new URL(`/og/${ogSlug}.png`, Astro.site);
|
||||
const pageUrl = new URL(Astro.url.pathname, Astro.site);
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
@@ -24,6 +32,14 @@ const showToc = headings.filter((h) => h.depth <= 3).length >= 2;
|
||||
<title>{title}{isHome ? '' : ' // Wesley Ray'}</title>
|
||||
<meta name="theme-color" content="#0b0d12" />
|
||||
{description && <meta name="description" content={description} />}
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:type" content={isHome ? 'website' : 'article'} />
|
||||
<meta property="og:url" content={pageUrl} />
|
||||
{description && <meta property="og:description" content={description} />}
|
||||
<meta property="og:image" content={ogImage} />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/jetbrains-mono-v13-latin-regular.woff2"
|
||||
@@ -61,6 +77,14 @@ const showToc = headings.filter((h) => h.depth <= 3).length >= 2;
|
||||
<span id="hq-text"></span>
|
||||
<span id="hq-attr" class="hq-attr"></span>
|
||||
</div>
|
||||
{
|
||||
isHome && (
|
||||
<div id="live-stats" class="live-stats" hidden>
|
||||
<span class="live-dot" aria-hidden="true" />
|
||||
<span id="live-spotify" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</header>
|
||||
<main>
|
||||
<slot />
|
||||
@@ -85,6 +109,19 @@ const showToc = headings.filter((h) => h.depth <= 3).length >= 2;
|
||||
ticking at the lifetime average
|
||||
</p>
|
||||
</div>
|
||||
{
|
||||
COMMIT && (
|
||||
<p class="build-stamp">
|
||||
built {BUILT_AT} ET ·{' '}
|
||||
<a
|
||||
href={`https://git.c0smere.net/wes/garden-astro/commit/${COMMIT.replace('+', '')}`}
|
||||
>
|
||||
{COMMIT}
|
||||
</a>{' '}
|
||||
· {noteCount} notes
|
||||
</p>
|
||||
)
|
||||
}
|
||||
</footer>
|
||||
</div>
|
||||
<aside class="sidebar">
|
||||
@@ -119,6 +156,39 @@ const showToc = headings.filter((h) => h.depth <= 3).length >= 2;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Homepage live strip: weekly listening aggregates from the API.
|
||||
// Fail-closed: any error (or non-home page) leaves the slot hidden.
|
||||
const strip = document.getElementById('live-stats');
|
||||
if (strip) {
|
||||
try {
|
||||
const res = await fetch('https://api.c0smere.net/spotify/summary');
|
||||
if (!res.ok) throw new Error(String(res.status));
|
||||
const s = await res.json();
|
||||
const slot = document.getElementById('live-spotify')!;
|
||||
const put = (text: string, strong = false) => {
|
||||
const el = document.createElement(strong ? 'span' : 'span');
|
||||
if (strong) el.className = 'v';
|
||||
el.textContent = text;
|
||||
slot.append(el);
|
||||
};
|
||||
put(String(s.week_minutes), true);
|
||||
put(' min of listening this week');
|
||||
if (s.top_artist_month) {
|
||||
put(' · lately: ');
|
||||
put(s.top_artist_month, true);
|
||||
}
|
||||
if (s.top_genre_month) {
|
||||
put(' · ');
|
||||
put(s.top_genre_month, true);
|
||||
}
|
||||
strip.hidden = false;
|
||||
} catch {
|
||||
/* API down or blocked: strip stays hidden */
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Odometer: fetch totals once, then animate forward at the lifetime
|
||||
// average rate. Looks live, but deliberately never exposes current
|
||||
@@ -390,6 +460,38 @@ const showToc = headings.filter((h) => h.depth <= 3).length >= 2;
|
||||
margin-left: 0.4rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
.live-stats {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 0.55rem;
|
||||
margin: -0.75rem 0 1.75rem;
|
||||
padding-bottom: 0.85rem;
|
||||
border-bottom: 1px solid var(--hair);
|
||||
font-size: 0.78rem;
|
||||
color: var(--muted);
|
||||
}
|
||||
.live-stats .v {
|
||||
color: var(--fg);
|
||||
}
|
||||
.live-dot {
|
||||
flex: none;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: var(--link);
|
||||
align-self: center;
|
||||
animation: live-pulse 2.4s ease-in-out infinite;
|
||||
}
|
||||
@keyframes live-pulse {
|
||||
50% {
|
||||
opacity: 0.35;
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.live-dot {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- headings ---- */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
@@ -637,6 +739,17 @@ const showToc = headings.filter((h) => h.depth <= 3).length >= 2;
|
||||
margin-top: 0.35rem;
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
.build-stamp {
|
||||
margin-top: 1.25rem;
|
||||
font-size: 0.72rem;
|
||||
color: hsla(0, 0%, 100%, 0.4);
|
||||
}
|
||||
.build-stamp a {
|
||||
color: inherit;
|
||||
}
|
||||
.build-stamp a:hover {
|
||||
color: var(--link-bright);
|
||||
}
|
||||
|
||||
/* ---- homepage: typographic feed, like the blog's index ---- */
|
||||
.home main h1 {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// Build provenance for the footer stamp. Evaluated once per build (module
|
||||
// scope). The containerized build has no git binary, so deploy/build.sh
|
||||
// passes GARDEN_COMMIT in; local builds fall back to asking git directly.
|
||||
// A trailing "+" marks a build from a dirty tree.
|
||||
import { execSync } from 'node:child_process';
|
||||
|
||||
function detectCommit() {
|
||||
if (process.env.GARDEN_COMMIT) return process.env.GARDEN_COMMIT;
|
||||
try {
|
||||
const h = execSync('git rev-parse --short HEAD', {
|
||||
stdio: ['ignore', 'pipe', 'ignore'],
|
||||
})
|
||||
.toString()
|
||||
.trim();
|
||||
let dirty = '';
|
||||
try {
|
||||
execSync('git diff --quiet', { stdio: 'ignore' });
|
||||
} catch {
|
||||
dirty = '+';
|
||||
}
|
||||
return h + dirty;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export const COMMIT = detectCommit();
|
||||
|
||||
const fmt = new Intl.DateTimeFormat('en-CA', {
|
||||
dateStyle: 'short',
|
||||
timeStyle: 'short',
|
||||
hour12: false,
|
||||
timeZone: 'America/New_York',
|
||||
});
|
||||
export const BUILT_AT = fmt.format(new Date()).replace(', ', ' ');
|
||||
@@ -72,6 +72,7 @@ const contentLeadsWithTitle =
|
||||
title={title}
|
||||
description={entry?.data.description}
|
||||
headings={rendered?.headings ?? []}
|
||||
ogSlug={entry ? slugForId(entry.id) : undefined}
|
||||
>
|
||||
{!contentLeadsWithTitle && <h1>{title}</h1>}
|
||||
{Content && <Content />}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
// Build-time OG images: 1200x630 dark cards matching the site design,
|
||||
// one per note (plus /og/index.png for the homepage). satori renders an
|
||||
// element tree to SVG, resvg rasterizes to PNG. Base.astro points
|
||||
// og:image here via the ogSlug prop.
|
||||
import fs from 'node:fs';
|
||||
import type { APIRoute } from 'astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
import satori from 'satori';
|
||||
import { Resvg } from '@resvg/resvg-js';
|
||||
import { slugForId } from '../../lib/quartz-compat.mjs';
|
||||
|
||||
const FONT_DIR = 'node_modules/@fontsource/jetbrains-mono/files';
|
||||
const mono400 = fs.readFileSync(`${FONT_DIR}/jetbrains-mono-latin-400-normal.woff`);
|
||||
const mono800 = fs.readFileSync(`${FONT_DIR}/jetbrains-mono-latin-800-normal.woff`);
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const entries = await getCollection('garden', (e: any) => !e.data.draft);
|
||||
return entries.map((e: any) => {
|
||||
const isIndex = e.id === 'index';
|
||||
const title = isIndex
|
||||
? 'Wesley Ray'
|
||||
: (e.data.title ?? e.id.split('/').pop());
|
||||
const dir = e.id.includes('/') ? e.id.slice(0, e.id.lastIndexOf('/')) : '';
|
||||
return {
|
||||
params: { slug: isIndex ? 'index' : slugForId(e.id) },
|
||||
props: {
|
||||
title,
|
||||
dir,
|
||||
subtitle: isIndex ? 'projects, notes, and experiments' : dir,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export const GET: APIRoute = async ({ props }) => {
|
||||
const { title, subtitle } = props as { title: string; subtitle: string };
|
||||
const size = title.length > 55 ? 44 : title.length > 32 ? 56 : 68;
|
||||
|
||||
const svg = await satori(
|
||||
{
|
||||
type: 'div',
|
||||
props: {
|
||||
style: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#0b0d12',
|
||||
borderLeft: '14px solid #218107',
|
||||
padding: '64px 72px',
|
||||
fontFamily: 'JetBrains Mono',
|
||||
color: '#ffffff',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: 'div',
|
||||
props: {
|
||||
style: {
|
||||
display: 'flex',
|
||||
fontSize: '26px',
|
||||
color: 'rgba(255,255,255,0.64)',
|
||||
letterSpacing: '2px',
|
||||
},
|
||||
children: 'the garden // Wesley Ray',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'div',
|
||||
props: {
|
||||
style: {
|
||||
display: 'flex',
|
||||
fontSize: `${size}px`,
|
||||
fontWeight: 800,
|
||||
lineHeight: 1.25,
|
||||
letterSpacing: '-1px',
|
||||
},
|
||||
children: title,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'div',
|
||||
props: {
|
||||
style: {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
fontSize: '26px',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: 'div',
|
||||
props: {
|
||||
style: {
|
||||
display: 'flex',
|
||||
color: 'rgba(255,255,255,0.64)',
|
||||
},
|
||||
children: subtitle || ' ',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'div',
|
||||
props: {
|
||||
style: { display: 'flex', color: '#2fa50f' },
|
||||
children: 'garden.c0smere.net',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
width: 1200,
|
||||
height: 630,
|
||||
fonts: [
|
||||
{ name: 'JetBrains Mono', data: mono400, weight: 400, style: 'normal' },
|
||||
{ name: 'JetBrains Mono', data: mono800, weight: 800, style: 'normal' },
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const png = new Resvg(svg, {
|
||||
fitTo: { mode: 'width', value: 1200 },
|
||||
}).render().asPng();
|
||||
|
||||
return new Response(png, { headers: { 'Content-Type': 'image/png' } });
|
||||
};
|
||||
Reference in New Issue
Block a user