From bc7e8e6c8da315d3316eaa8330112d7209ca3dec Mon Sep 17 00:00:00 2001 From: Jon Bogaty Date: Mon, 27 Jul 2026 00:39:41 -0500 Subject: [PATCH] fix(site): correct stale package index and broken page metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two independent defects, both shipping on the live site. 1. Stale generated directory. src/data/directory/directory.json is generated from the package manifests but committed, and nothing regenerated it when PR #22 bumped paranoid-passwd to 3.7.0 — so the index kept advertising 3.6.5 for all three packagers. Regenerated, and added a CI step that re-runs the generator and fails on any diff, so the committed copy can no longer drift from the manifests silently. The step pins Node via .nvmrc. 2. Broken metadata inherited from the upstream Astro template: - og:image / twitter:image pointed at /og/.png, but this site generates no OG images at all — every page advertised a 404, and the home page emitted literal "og/undefined.png" (no slug prop). Removed the image tags and switched twitter:card to `summary`, which renders correctly without an image. getOGImage.ts and the unused @vercel/og dependency are deleted rather than left orphaned. - og:url pointed every page at the site root; now a real per-page canonical URL, and is emitted. - favicon and sitemap used root-absolute paths that 404 under the /pkgs base; now base-aware. - description was the template's hardcoded "Astro description"; now the per-page description callers already passed. - twitter:domain was the template's leftover codeagents.dev. `slug` was threaded through Article/Listing solely to feed getOGImage, so it is removed end-to-end rather than left as an unused prop. Verified: astro check clean, build green, node 2/2, ruby 5/5, homebrew + scoop validators pass, and the emitted HTML confirmed to contain per-page canonicals, /pkgs-based asset paths, real descriptions, and zero og:image or "undefined" references. Drift guard tested both ways: passes in sync, fails on a simulated manifest bump. --- .github/workflows/validate-packages.yml | 24 ++++ package.json | 1 - pnpm-lock.yaml | 156 ------------------------ src/data/directory/directory.json | 6 +- src/layouts/Article.astro | 4 +- src/layouts/BaseLayout.astro | 57 +++++---- src/layouts/Listing.astro | 4 +- src/util/getOGImage.ts | 14 --- 8 files changed, 64 insertions(+), 202 deletions(-) delete mode 100644 src/util/getOGImage.ts diff --git a/.github/workflows/validate-packages.yml b/.github/workflows/validate-packages.yml index 1acd2c0..b5112b6 100644 --- a/.github/workflows/validate-packages.yml +++ b/.github/workflows/validate-packages.yml @@ -113,3 +113,27 @@ jobs: ET.parse(path) print(f"Validated {len(files)} nuspec file(s)") PY + + # src/data/directory/directory.json is generated from the package + # manifests but committed to the repo, so it can silently go stale when a + # manifest is bumped without re-running the generator — which is how the + # site kept advertising paranoid-passwd 3.6.5 after it had shipped 3.7.0. + # Regenerate and fail if the committed copy differs. + - name: Set up Node + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + with: + node-version-file: ".nvmrc" + + - name: Check generated directory.json is up to date + shell: bash + run: | + set -euo pipefail + corepack enable + pnpm install --frozen-lockfile + node scripts/generate-directory.mjs + if ! git diff --quiet -- src/data/directory/directory.json; then + echo "::error::src/data/directory/directory.json is stale. Run 'node scripts/generate-directory.mjs' and commit the result." + git --no-pager diff -- src/data/directory/directory.json + exit 1 + fi + echo "directory.json is in sync with the package manifests" diff --git a/package.json b/package.json index 7d2dc94..98807e1 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "@rgrove/parse-xml": "^4.2.2", "@tailwindcss/vite": "^4.3.3", "@types/node": "^26.1.1", - "@vercel/og": "^0.11.1", "astro": "^5.18.2", "astro-color-scheme": "^1.1.5", "nanostores": "^1.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa11075..2721e55 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,9 +53,6 @@ importers: '@types/node': specifier: ^26.1.1 version: 26.1.1 - '@vercel/og': - specifier: ^0.11.1 - version: 0.11.1 astro: specifier: ^5.18.2 version: 5.18.2(@types/node@26.1.1)(jiti@2.7.0)(lightningcss@1.32.0)(rollup@4.61.1)(typescript@5.9.3)(yaml@2.8.4) @@ -1053,10 +1050,6 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@resvg/resvg-wasm@2.4.0': - resolution: {integrity: sha512-C7c51Nn4yTxXFKvgh2txJFNweaVcfUPQxwEUFw4aWsCmfiBDJsTSwviIF8EcwjQ6k8bPyMWCl1vw4BdxE569Cg==} - engines: {node: '>= 10'} - '@rgrove/parse-xml@4.2.2': resolution: {integrity: sha512-KJpwSfVwrZ1Ab9KU4oRwG0VefGpveSt/w/j1m6YkJkB5KhdDbN/7BS0ojcLCzrG3/YGFhtfFHKVBkrms6w8Org==} engines: {node: '>=14.0.0'} @@ -1400,11 +1393,6 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@shuding/opentype.js@1.4.0-beta.0': - resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==} - engines: {node: '>= 8.0.0'} - hasBin: true - '@sindresorhus/merge-streams@4.0.0': resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} @@ -1565,10 +1553,6 @@ packages: resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} deprecated: Potential CWE-502 - Update to 1.3.1 or higher - '@vercel/og@0.11.1': - resolution: {integrity: sha512-02rXXRABFq1B03w3aNhcVfxkY+8Ba5QFi4ax0zS0oOiD/LL9WUd/LA7BjVPakrQmVhIBjuo2oBM5U25R9IuXMg==} - engines: {node: '>=16'} - '@vitejs/plugin-vue-jsx@4.2.0': resolution: {integrity: sha512-DSTrmrdLp+0LDNF77fqrKfx7X0ErRbOcUAgJL/HbSesqQwoUvUQ4uYQqaex+rovqgGcoPqVk+AwUh3v9CuiYIw==} engines: {node: ^18.0.0 || >=20.0.0} @@ -1760,10 +1744,6 @@ packages: base-64@1.0.0: resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} - base64-js@0.0.8: - resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==} - engines: {node: '>= 0.4'} - baseline-browser-mapping@2.10.19: resolution: {integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==} engines: {node: '>=6.0.0'} @@ -1795,9 +1775,6 @@ packages: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - camelize@1.0.1: - resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - caniuse-lite@1.0.30001788: resolution: {integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==} @@ -1906,26 +1883,9 @@ packages: crossws@0.3.5: resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} - css-background-parser@0.1.0: - resolution: {integrity: sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==} - - css-box-shadow@1.0.0-3: - resolution: {integrity: sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==} - - css-color-keywords@1.0.0: - resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} - engines: {node: '>=4'} - - css-gradient-parser@0.0.17: - resolution: {integrity: sha512-w2Xy9UMMwlKtou0vlRnXvWglPAceXCTtcmVSo8ZBUvqCV5aXEFP/PC6d+I464810I9FT++UACwTD5511bmGPUg==} - engines: {node: '>=16'} - css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} - css-to-react-native@3.2.0: - resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} - css-tree@2.2.1: resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} @@ -2032,10 +1992,6 @@ packages: emmet@2.4.11: resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==} - emoji-regex-xs@2.0.1: - resolution: {integrity: sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g==} - engines: {node: '>=10.0.0'} - emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -2090,9 +2046,6 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} @@ -2161,9 +2114,6 @@ packages: picomatch: optional: true - fflate@0.7.4: - resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} - figures@6.1.0: resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} engines: {node: '>=18'} @@ -2257,10 +2207,6 @@ packages: hastscript@9.0.1: resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} - hex-rgb@4.3.0: - resolution: {integrity: sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==} - engines: {node: '>=6'} - hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} @@ -2460,9 +2406,6 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} - linebreak@1.1.0: - resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==} - local-pkg@1.1.2: resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} engines: {node: '>=14'} @@ -2764,12 +2707,6 @@ packages: package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} - pako@0.2.9: - resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} - - parse-css-color@0.2.1: - resolution: {integrity: sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg==} - parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} @@ -2833,9 +2770,6 @@ packages: resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} engines: {node: '>=4'} - postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.15: resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} @@ -2991,10 +2925,6 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - satori@0.25.0: - resolution: {integrity: sha512-utINfLxrYrmSnLvxFT4ZwgwWa8KOjrz7ans32V5wItgHVmzESl/9i33nE38uG0miycab8hUqQtDlOpqrIpB/iw==} - engines: {node: '>=16'} - sax@1.6.0: resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} engines: {node: '>=11.0.0'} @@ -3083,9 +3013,6 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string.prototype.codepointat@0.2.1: - resolution: {integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==} - stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} @@ -3205,9 +3132,6 @@ packages: resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} engines: {node: '>=20.18.1'} - unicode-trie@2.0.0: - resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} - unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -3643,9 +3567,6 @@ packages: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} - yoga-layout@3.2.1: - resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} - zod-to-json-schema@3.25.2: resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} peerDependencies: @@ -4513,8 +4434,6 @@ snapshots: '@polka/url@1.0.0-next.29': {} - '@resvg/resvg-wasm@2.4.0': {} - '@rgrove/parse-xml@4.2.2': {} '@rolldown/pluginutils@1.0.0-rc.15': {} @@ -4727,11 +4646,6 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} - '@shuding/opentype.js@1.4.0-beta.0': - dependencies: - fflate: 0.7.4 - string.prototype.codepointat: 0.2.1 - '@sindresorhus/merge-streams@4.0.0': {} '@tailwindcss/node@4.3.3': @@ -4865,13 +4779,6 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vercel/og@0.11.1': - dependencies: - '@resvg/resvg-wasm': 2.4.0 - satori: 0.25.0 - optionalDependencies: - sharp: 0.34.5 - '@vitejs/plugin-vue-jsx@4.2.0(vite@6.4.2(@types/node@26.1.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4))(vue@3.5.40(typescript@5.9.3))': dependencies: '@babel/core': 7.29.0 @@ -5243,8 +5150,6 @@ snapshots: base-64@1.0.0: {} - base64-js@0.0.8: {} - baseline-browser-mapping@2.10.19: {} birpc@2.9.0: {} @@ -5278,8 +5183,6 @@ snapshots: camelcase@8.0.0: {} - camelize@1.0.1: {} - caniuse-lite@1.0.30001788: {} ccount@2.0.1: {} @@ -5379,14 +5282,6 @@ snapshots: dependencies: uncrypto: 0.1.3 - css-background-parser@0.1.0: {} - - css-box-shadow@1.0.0-3: {} - - css-color-keywords@1.0.0: {} - - css-gradient-parser@0.0.17: {} - css-select@5.2.2: dependencies: boolbase: 1.0.0 @@ -5395,12 +5290,6 @@ snapshots: domutils: 3.2.2 nth-check: 2.1.1 - css-to-react-native@3.2.0: - dependencies: - camelize: 1.0.1 - css-color-keywords: 1.0.0 - postcss-value-parser: 4.2.0 - css-tree@2.2.1: dependencies: mdn-data: 2.0.28 @@ -5492,8 +5381,6 @@ snapshots: '@emmetio/abbreviation': 2.3.3 '@emmetio/css-abbreviation': 2.1.8 - emoji-regex-xs@2.0.1: {} - emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} @@ -5596,8 +5483,6 @@ snapshots: escalade@3.2.0: {} - escape-html@1.0.3: {} - escape-string-regexp@5.0.0: {} eslint-visitor-keys@5.0.1: {} @@ -5680,8 +5565,6 @@ snapshots: optionalDependencies: picomatch: 4.0.4 - fflate@0.7.4: {} - figures@6.1.0: dependencies: is-unicode-supported: 2.1.0 @@ -5866,8 +5749,6 @@ snapshots: property-information: 7.2.0 space-separated-tokens: 2.0.2 - hex-rgb@4.3.0: {} - hookable@5.5.3: {} html-escaper@3.0.3: {} @@ -6007,11 +5888,6 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 - linebreak@1.1.0: - dependencies: - base64-js: 0.0.8 - unicode-trie: 2.0.0 - local-pkg@1.1.2: dependencies: mlly: 1.8.2 @@ -6573,13 +6449,6 @@ snapshots: package-manager-detector@1.6.0: {} - pako@0.2.9: {} - - parse-css-color@0.2.1: - dependencies: - color-name: 1.1.4 - hex-rgb: 4.3.0 - parse-entities@4.0.2: dependencies: '@types/unist': 2.0.11 @@ -6651,8 +6520,6 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-value-parser@4.2.0: {} - postcss@8.5.15: dependencies: nanoid: 3.3.12 @@ -6922,20 +6789,6 @@ snapshots: safer-buffer@2.1.2: {} - satori@0.25.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.2.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 - sax@1.6.0: {} semver@6.3.1: {} @@ -7067,8 +6920,6 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 - string.prototype.codepointat@0.2.1: {} - stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 @@ -7176,11 +7027,6 @@ snapshots: undici@7.25.0: {} - unicode-trie@2.0.0: - dependencies: - pako: 0.2.9 - tiny-inflate: 1.0.3 - unicorn-magic@0.3.0: {} unified@11.0.5: @@ -7566,8 +7412,6 @@ snapshots: yoctocolors@2.1.2: {} - yoga-layout@3.2.1: {} - zod-to-json-schema@3.25.2(zod@3.25.76): dependencies: zod: 3.25.76 diff --git a/src/data/directory/directory.json b/src/data/directory/directory.json index f42e690..35611a7 100644 --- a/src/data/directory/directory.json +++ b/src/data/directory/directory.json @@ -11,9 +11,9 @@ "link": "https://jonbogaty.com/paranoid-passwd/", "featured": false, "packagers": { - "chocolatey": "3.6.5", - "homebrew-formula": "3.6.5", - "scoop": "3.6.5" + "chocolatey": "3.7.0", + "homebrew-formula": "3.7.0", + "scoop": "3.7.0" }, "license": "GPL-3.0-only" }, diff --git a/src/layouts/Article.astro b/src/layouts/Article.astro index cd3c3c6..7247ff6 100644 --- a/src/layouts/Article.astro +++ b/src/layouts/Article.astro @@ -2,7 +2,7 @@ import "@fontsource/gabarito"; import BaseLayout from "./BaseLayout.astro"; import AppProse from "../components/app/Prose.astro"; -const { frontmatter, slug } = Astro.props; +const { frontmatter } = Astro.props; import themeConfig from "@util/themeConfig"; import AppShell from "@components/app/AppShell.astro"; const siteTitle = themeConfig.general.title; @@ -10,7 +10,7 @@ const title = frontmatter?.title || siteTitle; const description = frontmatter?.description; --- - +
diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 5db016e..aadbce6 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -3,47 +3,56 @@ import "@fontsource-variable/gabarito"; import themeConfig from "@util/themeConfig"; import "../styles/global.css"; import { ClientRouter } from "astro:transitions"; -import { getOGImage } from "@util/getOGImage"; -const { title, slug } = Astro.props; +const { title, description } = Astro.props; const siteTitle = themeConfig.general.title; +const seo = themeConfig.general.seo; const calculatedTitle = title || siteTitle; +const calculatedDescription = description || seo.description; + +// Absolute, per-page canonical URL. Astro.site is the apex and Astro.url.pathname +// already carries the `/pkgs` base, so this resolves correctly for every route +// instead of pointing every page at the site root. +const canonicalURL = new URL(Astro.url.pathname, Astro.site ?? seo.url).href; + +// Base-aware asset paths — a bare "/favicon.svg" would resolve to the apex and +// 404, because the site is served under /pkgs. +const favicon = `${import.meta.env.BASE_URL}/favicon.svg`.replace(/\/{2,}/g, "/"); +const sitemap = `${import.meta.env.BASE_URL}/sitemap-index.xml`.replace(/\/{2,}/g, "/"); + +// The twitter:domain is the bare host of the canonical site. +const twitterDomain = new URL(seo.url).hostname; --- - - - + + + {calculatedTitle} - + - - + + + - - - - - - - - - - + + + + + + + + diff --git a/src/layouts/Listing.astro b/src/layouts/Listing.astro index dd5f1ff..2f7315e 100644 --- a/src/layouts/Listing.astro +++ b/src/layouts/Listing.astro @@ -1,7 +1,7 @@ --- import BaseLayout from "./BaseLayout.astro"; import AppProse from "../components/app/Prose.astro"; -const { frontmatter, slug } = Astro.props; +const { frontmatter } = Astro.props; import themeConfig from "@util/themeConfig"; import { Icon } from "astro-icon/components"; import AppShell from "@components/app/AppShell.astro"; @@ -18,7 +18,7 @@ const pageHeader = themeConfig.listings.pageHeader; const sidebar = config.layout.sidebar; --- - + { sidebar ? ( diff --git a/src/util/getOGImage.ts b/src/util/getOGImage.ts deleted file mode 100644 index 04d78a8..0000000 --- a/src/util/getOGImage.ts +++ /dev/null @@ -1,14 +0,0 @@ -import themeConfig from "./themeConfig" - -function getBasePath(): string { - if (process.env.NODE_ENV === 'development') { - return 'http://localhost:4321'; - } - - return themeConfig.general.seo.url; -} - -export function getOGImage(slug: string) { - let basePath: string = getBasePath(); - return `${basePath}/og/${slug}.png`; -} \ No newline at end of file