Compare commits
43 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ec7442da30 | |||
| 7a674694a7 | |||
| d8768998e2 | |||
| 2f39f3d62d | |||
| 28a57aca9a | |||
| e77351e5dd | |||
| fd1d015a18 | |||
| f2bbfbf1b4 | |||
| 4860085aef | |||
| e3be0e92cb | |||
| 1dbd3d662c | |||
| 199f3d1429 | |||
| 74a3a71090 | |||
| 7966746711 | |||
| 7e0380a324 | |||
| 7921721425 | |||
| 5fa6e68b37 | |||
| a71eb0f975 | |||
| 087403f70f | |||
| 25a83048d5 | |||
| 8f09af3829 | |||
| 7ff435d619 | |||
| 9d21f0282b | |||
| 5cc77e537b | |||
| 05dd11db99 | |||
| 2e4cf74810 | |||
| 5140c1fe55 | |||
| d9abb4bd53 | |||
| 5104dc3176 | |||
| 5d2802aca7 | |||
| f0bb8f9272 | |||
| e4081c42e4 | |||
| 9e4eb6ef15 | |||
| a6f7c1153c | |||
| cea29e7a01 | |||
| eaecdbcf23 | |||
| 9d69a6cc67 | |||
| 9b4312b49d | |||
| bb335badf6 | |||
| 85f9b148de | |||
| ca81b780ce | |||
| 0f28734a2d | |||
| df5b89e5b1 |
18 changed files with 732 additions and 54 deletions
6
.vscode/extensions.json
vendored
6
.vscode/extensions.json
vendored
|
|
@ -1,4 +1,8 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"recommendations": [
|
||||
"astro-build.astro-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
|
|
|
|||
30
README.md
30
README.md
|
|
@ -22,12 +22,30 @@ $ pnpm i
|
|||
|
||||
## Commands
|
||||
|
||||
| Command | Action |
|
||||
| ------------------- | ---------------------------------------------- |
|
||||
| `pnpm run dev` | start dev server |
|
||||
| `pnpm run build` | generate static files to `dist` directory |
|
||||
| `pnpm run deploy` | upload to my server |
|
||||
| `pnpm run prep:now` | back up and clear current `now page` constants |
|
||||
| Command | Action |
|
||||
| ----------------------------- | ---------------------------------------------- |
|
||||
| `pnpm run dev` | start dev server |
|
||||
| `pnpm run build` | generate static files to `dist` directory |
|
||||
| `pnpm run deploy` | upload to my server |
|
||||
| `pnpm run prep:now` | back up and clear current `now page` constants |
|
||||
| `pnpm run patch:build:deploy` | increment version, build, then upload |
|
||||
|
||||
## Testing
|
||||
|
||||
This project uses Vitest for unit tests. The test script is defined in `package.json` as `vitest run .`.
|
||||
|
||||
Run tests locally with pnpm (recommended):
|
||||
|
||||
```bash
|
||||
# install dependencies (if you haven't already)
|
||||
pnpm i
|
||||
|
||||
# run tests once
|
||||
pnpm test
|
||||
|
||||
# run Vitest in interactive/watch mode
|
||||
pnpm exec vitest
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import tseslint from 'typescript-eslint'
|
|||
import astroSwGlobals from '@ayco/astro-sw/globals'
|
||||
import astroParser from 'astro-eslint-parser'
|
||||
|
||||
import { includeIgnoreFile } from '@eslint/compat'
|
||||
import { includeIgnoreFile } from '@eslint/config-helpers'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
|
|
|
|||
25
package.json
25
package.json
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@ayco/personal-website",
|
||||
"type": "module",
|
||||
"version": "1.3.68",
|
||||
"version": "1.3.81",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"astro": "astro",
|
||||
|
|
@ -11,20 +11,24 @@
|
|||
"preview": "astro preview",
|
||||
"lint": "eslint . --config eslint.config.mjs --cache",
|
||||
"lint:fix": "eslint . --config eslint.config.mjs --fix",
|
||||
"format": "prettier . --write",
|
||||
"check": "npm run format && npm run lint",
|
||||
"fmt": "prettier . --config prettier.config.mjs --check",
|
||||
"fmt:fix": "prettier . --config prettier.config.mjs --write",
|
||||
"check": "npm run fmt && npm run lint",
|
||||
"deploy": "eval $(grep '^HOST' .env) && scp -r dist ayo@$HOST:~/ayco.io-flask",
|
||||
"patch:build:deploy": "npm version patch && npm run build && npm run deploy",
|
||||
"pbd": "npm run patch:build:deploy",
|
||||
"build:preview": "npm run build && astro preview",
|
||||
"build:deploy": "npm run build && npm run deploy",
|
||||
"copy:dist": "npm run build && cp -R dist ../ayco.io-flask/",
|
||||
"prepare": "husky",
|
||||
"prep:now": "npx jiti ./commands/prep-now.js"
|
||||
"prep:now": "npx jiti ./commands/prep-now.js",
|
||||
"test": "vitest run ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/sitemap": "^3.7.2",
|
||||
"@ayco/astro-sw": "^1.0.0",
|
||||
"@eslint/compat": "^2.1.0",
|
||||
"@eslint/config-helpers": "^0.6.0",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@iconify-json/mdi": "^1.2.3",
|
||||
"@iconify-json/simple-icons": "^1.2.82",
|
||||
|
|
@ -48,22 +52,25 @@
|
|||
"rehype-stringify": "^10.0.1",
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.1.2",
|
||||
"sharp": "^0.34.5",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.3",
|
||||
"unified": "^11.0.5",
|
||||
"vite-plugin-static-copy": "^4.1.0"
|
||||
"vite-plugin-static-copy": "^4.1.0",
|
||||
"vitest": "^4.1.7",
|
||||
"vitest-dom": "^0.1.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,mjs,astro,ts}": [
|
||||
"prettier --write",
|
||||
"eslint --fix"
|
||||
"prettier . --config prettier.config.mjs --write",
|
||||
"eslint . --config eslint.config.mjs --fix"
|
||||
],
|
||||
"*.json": [
|
||||
"prettier --write"
|
||||
"prettier . --config prettier.config.mjs --write"
|
||||
]
|
||||
},
|
||||
"packageManager": "pnpm@10.33.2",
|
||||
"packageManager": "pnpm@11.5.2+sha512.71c631e382066efc25625d5cf029075de07b61b37f6e27350fbd84b1bda5864c8c1967adc280776b45c30a715c0359a3be08fef42d5bb09e2b99029979692916",
|
||||
"dependencies": {
|
||||
"@ayo-run/status-indicator": "^2.1.2",
|
||||
"web-component-base": "^4.1.2"
|
||||
|
|
|
|||
298
pnpm-lock.yaml
298
pnpm-lock.yaml
|
|
@ -24,6 +24,9 @@ importers:
|
|||
'@eslint/compat':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0(eslint@10.4.0(jiti@2.7.0))
|
||||
'@eslint/config-helpers':
|
||||
specifier: ^0.6.0
|
||||
version: 0.6.0
|
||||
'@eslint/js':
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1(eslint@10.4.0(jiti@2.7.0))
|
||||
|
|
@ -93,6 +96,9 @@ importers:
|
|||
remark-rehype:
|
||||
specifier: ^11.1.2
|
||||
version: 11.1.2
|
||||
sharp:
|
||||
specifier: ^0.34.5
|
||||
version: 0.34.5
|
||||
tslib:
|
||||
specifier: ^2.8.1
|
||||
version: 2.8.1
|
||||
|
|
@ -108,6 +114,12 @@ importers:
|
|||
vite-plugin-static-copy:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))
|
||||
vitest:
|
||||
specifier: ^4.1.7
|
||||
version: 4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))
|
||||
vitest-dom:
|
||||
specifier: ^0.1.1
|
||||
version: 0.1.1(vitest@4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0)))
|
||||
|
||||
packages:
|
||||
|
||||
|
|
@ -785,9 +797,18 @@ packages:
|
|||
'@shikijs/vscode-textmate@10.0.2':
|
||||
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
|
||||
|
||||
'@standard-schema/spec@1.1.0':
|
||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||
|
||||
'@types/chai@5.2.3':
|
||||
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
|
||||
|
||||
'@types/debug@4.1.13':
|
||||
resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==}
|
||||
|
||||
'@types/deep-eql@4.0.2':
|
||||
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
|
||||
|
||||
'@types/esrecurse@4.3.1':
|
||||
resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
|
||||
|
||||
|
|
@ -889,6 +910,35 @@ packages:
|
|||
'@ungap/structured-clone@1.3.1':
|
||||
resolution: {integrity: sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==}
|
||||
|
||||
'@vitest/expect@4.1.7':
|
||||
resolution: {integrity: sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==}
|
||||
|
||||
'@vitest/mocker@4.1.7':
|
||||
resolution: {integrity: sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==}
|
||||
peerDependencies:
|
||||
msw: ^2.4.9
|
||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
msw:
|
||||
optional: true
|
||||
vite:
|
||||
optional: true
|
||||
|
||||
'@vitest/pretty-format@4.1.7':
|
||||
resolution: {integrity: sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==}
|
||||
|
||||
'@vitest/runner@4.1.7':
|
||||
resolution: {integrity: sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==}
|
||||
|
||||
'@vitest/snapshot@4.1.7':
|
||||
resolution: {integrity: sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==}
|
||||
|
||||
'@vitest/spy@4.1.7':
|
||||
resolution: {integrity: sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==}
|
||||
|
||||
'@vitest/utils@4.1.7':
|
||||
resolution: {integrity: sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==}
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
|
|
@ -951,6 +1001,10 @@ packages:
|
|||
resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
assertion-error@2.0.1:
|
||||
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ast-types-flow@0.0.8:
|
||||
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
|
||||
|
||||
|
|
@ -1039,6 +1093,14 @@ packages:
|
|||
ccount@2.0.1:
|
||||
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
|
||||
|
||||
chai@6.2.2:
|
||||
resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
chalk@5.6.2:
|
||||
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
|
||||
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
|
||||
|
||||
character-entities-html4@2.1.0:
|
||||
resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
|
||||
|
||||
|
|
@ -1111,6 +1173,9 @@ packages:
|
|||
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
|
||||
engines: {node: ^14.18.0 || >=16.10.0}
|
||||
|
||||
convert-source-map@2.0.0:
|
||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||
|
||||
cookie-es@1.2.3:
|
||||
resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==}
|
||||
|
||||
|
|
@ -1144,6 +1209,9 @@ packages:
|
|||
resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
css.escape@1.5.1:
|
||||
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
|
||||
|
||||
cssesc@3.0.0:
|
||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||
engines: {node: '>=4'}
|
||||
|
|
@ -1215,6 +1283,9 @@ packages:
|
|||
resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
|
||||
dom-accessibility-api@0.6.3:
|
||||
resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
|
||||
|
||||
dom-serializer@2.0.0:
|
||||
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
|
||||
|
||||
|
|
@ -1379,6 +1450,9 @@ packages:
|
|||
estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
|
||||
estree-walker@3.0.3:
|
||||
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
||||
|
||||
esutils@2.0.3:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -1386,6 +1460,10 @@ packages:
|
|||
eventemitter3@5.0.4:
|
||||
resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}
|
||||
|
||||
expect-type@1.3.0:
|
||||
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
exsolve@1.0.8:
|
||||
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
|
||||
|
||||
|
|
@ -1631,6 +1709,10 @@ packages:
|
|||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||
engines: {node: '>=0.8.19'}
|
||||
|
||||
indent-string@5.0.0:
|
||||
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
internal-slot@1.1.0:
|
||||
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -1829,6 +1911,9 @@ packages:
|
|||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
lodash-es@4.18.1:
|
||||
resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
|
||||
|
||||
log-update@6.1.0:
|
||||
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -2229,6 +2314,10 @@ packages:
|
|||
resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
|
||||
engines: {node: '>= 20.19.0'}
|
||||
|
||||
redent@4.0.0:
|
||||
resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -2382,6 +2471,9 @@ packages:
|
|||
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
siginfo@2.0.0:
|
||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||
|
||||
signal-exit@4.1.0:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
|
|
@ -2413,6 +2505,12 @@ packages:
|
|||
space-separated-tokens@2.0.2:
|
||||
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
||||
|
||||
stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
|
||||
std-env@4.1.0:
|
||||
resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==}
|
||||
|
||||
stop-iteration-iterator@1.1.0:
|
||||
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -2455,6 +2553,10 @@ packages:
|
|||
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-indent@4.1.1:
|
||||
resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
suf-log@2.5.3:
|
||||
resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==}
|
||||
|
||||
|
|
@ -2479,6 +2581,9 @@ packages:
|
|||
tiny-inflate@1.0.3:
|
||||
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
|
||||
|
||||
tinybench@2.9.0:
|
||||
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||
|
||||
tinyclip@0.1.12:
|
||||
resolution: {integrity: sha512-Ae3OVUqifDw0wBriIBS7yVaW44Dp6eSHQcyq4Igc7eN2TJH/2YsicswaW+J/OuMvhpDPOKEgpAZCjkb4hpoyeA==}
|
||||
engines: {node: ^16.14.0 || >= 17.3.0}
|
||||
|
|
@ -2491,6 +2596,10 @@ packages:
|
|||
resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
tinyrainbow@3.1.0:
|
||||
resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
to-regex-range@5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
|
@ -2729,6 +2838,52 @@ packages:
|
|||
vite:
|
||||
optional: true
|
||||
|
||||
vitest-dom@0.1.1:
|
||||
resolution: {integrity: sha512-n/bonR2hcRHCE5hlzG/P0yTXTUXx/gPtsaeUWP86ADfwo/+dHDpnTTV14qY7+kevsUbOZFYECu77MXY7AA0QSA==}
|
||||
peerDependencies:
|
||||
vitest: '>=0.31.0'
|
||||
|
||||
vitest@4.1.7:
|
||||
resolution: {integrity: sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==}
|
||||
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@edge-runtime/vm': '*'
|
||||
'@opentelemetry/api': ^1.9.0
|
||||
'@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
|
||||
'@vitest/browser-playwright': 4.1.7
|
||||
'@vitest/browser-preview': 4.1.7
|
||||
'@vitest/browser-webdriverio': 4.1.7
|
||||
'@vitest/coverage-istanbul': 4.1.7
|
||||
'@vitest/coverage-v8': 4.1.7
|
||||
'@vitest/ui': 4.1.7
|
||||
happy-dom: '*'
|
||||
jsdom: '*'
|
||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
'@edge-runtime/vm':
|
||||
optional: true
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
'@types/node':
|
||||
optional: true
|
||||
'@vitest/browser-playwright':
|
||||
optional: true
|
||||
'@vitest/browser-preview':
|
||||
optional: true
|
||||
'@vitest/browser-webdriverio':
|
||||
optional: true
|
||||
'@vitest/coverage-istanbul':
|
||||
optional: true
|
||||
'@vitest/coverage-v8':
|
||||
optional: true
|
||||
'@vitest/ui':
|
||||
optional: true
|
||||
happy-dom:
|
||||
optional: true
|
||||
jsdom:
|
||||
optional: true
|
||||
|
||||
web-component-base@4.1.2:
|
||||
resolution: {integrity: sha512-Jti4FHgCcwtsFWJ+PPwFNhTm5AJVIHrTXDew0rk2Y3b8EChRIE5xr6fmUni43tOhc6w8HatvR3k+qnxjXr/7Mw==}
|
||||
|
||||
|
|
@ -2769,6 +2924,11 @@ packages:
|
|||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
|
||||
why-is-node-running@2.3.0:
|
||||
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
word-wrap@1.2.5:
|
||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -3098,8 +3258,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@img/colour@1.1.0':
|
||||
optional: true
|
||||
'@img/colour@1.1.0': {}
|
||||
|
||||
'@img/sharp-darwin-arm64@0.34.5':
|
||||
optionalDependencies:
|
||||
|
|
@ -3340,10 +3499,19 @@ snapshots:
|
|||
|
||||
'@shikijs/vscode-textmate@10.0.2': {}
|
||||
|
||||
'@standard-schema/spec@1.1.0': {}
|
||||
|
||||
'@types/chai@5.2.3':
|
||||
dependencies:
|
||||
'@types/deep-eql': 4.0.2
|
||||
assertion-error: 2.0.1
|
||||
|
||||
'@types/debug@4.1.13':
|
||||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
|
||||
'@types/deep-eql@4.0.2': {}
|
||||
|
||||
'@types/esrecurse@4.3.1': {}
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
|
@ -3479,6 +3647,47 @@ snapshots:
|
|||
|
||||
'@ungap/structured-clone@1.3.1': {}
|
||||
|
||||
'@vitest/expect@4.1.7':
|
||||
dependencies:
|
||||
'@standard-schema/spec': 1.1.0
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/spy': 4.1.7
|
||||
'@vitest/utils': 4.1.7
|
||||
chai: 6.2.2
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
'@vitest/mocker@4.1.7(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))':
|
||||
dependencies:
|
||||
'@vitest/spy': 4.1.7
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0)
|
||||
|
||||
'@vitest/pretty-format@4.1.7':
|
||||
dependencies:
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
'@vitest/runner@4.1.7':
|
||||
dependencies:
|
||||
'@vitest/utils': 4.1.7
|
||||
pathe: 2.0.3
|
||||
|
||||
'@vitest/snapshot@4.1.7':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 4.1.7
|
||||
'@vitest/utils': 4.1.7
|
||||
magic-string: 0.30.21
|
||||
pathe: 2.0.3
|
||||
|
||||
'@vitest/spy@4.1.7': {}
|
||||
|
||||
'@vitest/utils@4.1.7':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 4.1.7
|
||||
convert-source-map: 2.0.0
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.16.0):
|
||||
dependencies:
|
||||
acorn: 8.16.0
|
||||
|
|
@ -3553,6 +3762,8 @@ snapshots:
|
|||
get-intrinsic: 1.3.0
|
||||
is-array-buffer: 3.0.5
|
||||
|
||||
assertion-error@2.0.1: {}
|
||||
|
||||
ast-types-flow@0.0.8: {}
|
||||
|
||||
astro-eslint-parser@1.4.0:
|
||||
|
|
@ -3736,6 +3947,10 @@ snapshots:
|
|||
|
||||
ccount@2.0.1: {}
|
||||
|
||||
chai@6.2.2: {}
|
||||
|
||||
chalk@5.6.2: {}
|
||||
|
||||
character-entities-html4@2.1.0: {}
|
||||
|
||||
character-entities-legacy@3.0.0: {}
|
||||
|
|
@ -3812,6 +4027,8 @@ snapshots:
|
|||
|
||||
consola@3.4.2: {}
|
||||
|
||||
convert-source-map@2.0.0: {}
|
||||
|
||||
cookie-es@1.2.3: {}
|
||||
|
||||
cookie@1.1.1: {}
|
||||
|
|
@ -3851,6 +4068,8 @@ snapshots:
|
|||
|
||||
css-what@6.2.2: {}
|
||||
|
||||
css.escape@1.5.1: {}
|
||||
|
||||
cssesc@3.0.0: {}
|
||||
|
||||
csso@5.0.5:
|
||||
|
|
@ -3905,8 +4124,7 @@ snapshots:
|
|||
|
||||
destr@2.0.5: {}
|
||||
|
||||
detect-libc@2.1.2:
|
||||
optional: true
|
||||
detect-libc@2.1.2: {}
|
||||
|
||||
devalue@5.8.1: {}
|
||||
|
||||
|
|
@ -3916,6 +4134,8 @@ snapshots:
|
|||
|
||||
diff@8.0.4: {}
|
||||
|
||||
dom-accessibility-api@0.6.3: {}
|
||||
|
||||
dom-serializer@2.0.0:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
|
|
@ -4197,10 +4417,16 @@ snapshots:
|
|||
|
||||
estree-walker@2.0.2: {}
|
||||
|
||||
estree-walker@3.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.9
|
||||
|
||||
esutils@2.0.3: {}
|
||||
|
||||
eventemitter3@5.0.4: {}
|
||||
|
||||
expect-type@1.3.0: {}
|
||||
|
||||
exsolve@1.0.8: {}
|
||||
|
||||
extend@3.0.2: {}
|
||||
|
|
@ -4504,6 +4730,8 @@ snapshots:
|
|||
|
||||
imurmurhash@0.1.4: {}
|
||||
|
||||
indent-string@5.0.0: {}
|
||||
|
||||
internal-slot@1.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
|
@ -4707,6 +4935,8 @@ snapshots:
|
|||
dependencies:
|
||||
p-locate: 5.0.0
|
||||
|
||||
lodash-es@4.18.1: {}
|
||||
|
||||
log-update@6.1.0:
|
||||
dependencies:
|
||||
ansi-escapes: 7.3.0
|
||||
|
|
@ -5291,6 +5521,11 @@ snapshots:
|
|||
|
||||
readdirp@5.0.0: {}
|
||||
|
||||
redent@4.0.0:
|
||||
dependencies:
|
||||
indent-string: 5.0.0
|
||||
strip-indent: 4.1.1
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
dependencies:
|
||||
call-bind: 1.0.9
|
||||
|
|
@ -5541,7 +5776,6 @@ snapshots:
|
|||
'@img/sharp-win32-arm64': 0.34.5
|
||||
'@img/sharp-win32-ia32': 0.34.5
|
||||
'@img/sharp-win32-x64': 0.34.5
|
||||
optional: true
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
|
|
@ -5588,6 +5822,8 @@ snapshots:
|
|||
side-channel-map: 1.0.1
|
||||
side-channel-weakmap: 1.0.2
|
||||
|
||||
siginfo@2.0.0: {}
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
sisteransi@1.0.5: {}
|
||||
|
|
@ -5615,6 +5851,10 @@ snapshots:
|
|||
|
||||
space-separated-tokens@2.0.2: {}
|
||||
|
||||
stackback@0.0.2: {}
|
||||
|
||||
std-env@4.1.0: {}
|
||||
|
||||
stop-iteration-iterator@1.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
|
@ -5673,6 +5913,8 @@ snapshots:
|
|||
dependencies:
|
||||
ansi-regex: 6.2.2
|
||||
|
||||
strip-indent@4.1.1: {}
|
||||
|
||||
suf-log@2.5.3:
|
||||
dependencies:
|
||||
s.color: 0.0.15
|
||||
|
|
@ -5711,6 +5953,8 @@ snapshots:
|
|||
|
||||
tiny-inflate@1.0.3: {}
|
||||
|
||||
tinybench@2.9.0: {}
|
||||
|
||||
tinyclip@0.1.12: {}
|
||||
|
||||
tinyexec@1.1.2: {}
|
||||
|
|
@ -5720,6 +5964,8 @@ snapshots:
|
|||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
picomatch: 4.0.4
|
||||
|
||||
tinyrainbow@3.1.0: {}
|
||||
|
||||
to-regex-range@5.0.1:
|
||||
dependencies:
|
||||
is-number: 7.0.0
|
||||
|
|
@ -5920,6 +6166,43 @@ snapshots:
|
|||
optionalDependencies:
|
||||
vite: 7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0)
|
||||
|
||||
vitest-dom@0.1.1(vitest@4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))):
|
||||
dependencies:
|
||||
aria-query: 5.3.2
|
||||
chalk: 5.6.2
|
||||
css.escape: 1.5.1
|
||||
dom-accessibility-api: 0.6.3
|
||||
lodash-es: 4.18.1
|
||||
redent: 4.0.0
|
||||
vitest: 4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))
|
||||
|
||||
vitest@4.1.7(@types/node@25.8.0)(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0)):
|
||||
dependencies:
|
||||
'@vitest/expect': 4.1.7
|
||||
'@vitest/mocker': 4.1.7(vite@7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0))
|
||||
'@vitest/pretty-format': 4.1.7
|
||||
'@vitest/runner': 4.1.7
|
||||
'@vitest/snapshot': 4.1.7
|
||||
'@vitest/spy': 4.1.7
|
||||
'@vitest/utils': 4.1.7
|
||||
es-module-lexer: 2.1.0
|
||||
expect-type: 1.3.0
|
||||
magic-string: 0.30.21
|
||||
obug: 2.1.1
|
||||
pathe: 2.0.3
|
||||
picomatch: 4.0.4
|
||||
std-env: 4.1.0
|
||||
tinybench: 2.9.0
|
||||
tinyexec: 1.1.2
|
||||
tinyglobby: 0.2.16
|
||||
tinyrainbow: 3.1.0
|
||||
vite: 7.3.3(@types/node@25.8.0)(jiti@2.7.0)(yaml@2.9.0)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/node': 25.8.0
|
||||
transitivePeerDependencies:
|
||||
- msw
|
||||
|
||||
web-component-base@4.1.2: {}
|
||||
|
||||
web-namespaces@2.0.1: {}
|
||||
|
|
@ -5977,6 +6260,11 @@ snapshots:
|
|||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
why-is-node-running@2.3.0:
|
||||
dependencies:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
|
||||
word-wrap@1.2.5: {}
|
||||
|
||||
wrap-ansi@10.0.0:
|
||||
|
|
|
|||
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
allowBuilds:
|
||||
esbuild: false
|
||||
sharp: false
|
||||
web-component-base: false
|
||||
13
public/publickey.asc
Normal file
13
public/publickey.asc
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mDMEahs0NhYJKwYBBAHaRw8BAQdAV2CfblniKxklPgW9eYt2gBl0jMHLwtjrQaY+
|
||||
BQoWdIa0FkF5byBBeWNvIDxheW9AYXljby5pbz6ImQQTFgoAQRYhBBfxPV6P9zcr
|
||||
E1RcOGXmv2QVKTxlBQJqGzQ2AhsDBQkB4TOABQsJCAcCAiICBhUKCQgLAgQWAgMB
|
||||
Ah4HAheAAAoJEGXmv2QVKTxlIeYA/2WLvkDapBbVmGXoACAhqcTN93/CoPyzUbhN
|
||||
hHE6mmAUAQDHsgCHmh3S/Rn4NRE3Gb41kiPTBWHrlYLTj3Kiw0ASB7g4BGobNDYS
|
||||
CisGAQQBl1UBBQEBB0C6OEKEIPLaNDOM6JYhvvq0Q4Mk/B1eyZBKF/b4fQvlGgMB
|
||||
CAeIfgQYFgoAJhYhBBfxPV6P9zcrE1RcOGXmv2QVKTxlBQJqGzQ2AhsMBQkB4TOA
|
||||
AAoJEGXmv2QVKTxlMSQBAP5ta1kUFp3HAYwcun8qmoiVq1dEJSN1LnI7HlX4ucTl
|
||||
AP0YLC768PFTBm9CM5T1BE0xjJ7s4dZSrVoI4n8RSe1nCA==
|
||||
=MTsv
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
|
@ -45,7 +45,7 @@ const year = new Date().getFullYear()
|
|||
<p>
|
||||
Copyright © 2022-{year}
|
||||
<a href="/">Ayo Ayco</a>. This website <a
|
||||
href="https://ayos.blog/stopped-tracking-on-my-sites"
|
||||
href="https://v1.ayos.blog/stopped-tracking-on-my-sites"
|
||||
>does not track users</a
|
||||
>. See the <a href="https://git.ayo.run/ayo/ayco.io-astro">source code.</a>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export const footerLinks: Link[] = [
|
|||
},
|
||||
{
|
||||
text: 'Mastodon',
|
||||
url: 'https://main.elk.zone/social.ayco.io/@ayo',
|
||||
url: 'https://main.elk.zone/m.webtoo.ls/@ayo',
|
||||
icon: 'mastodon',
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { getImage } from 'astro:assets'
|
|||
|
||||
// fetch mastodon account
|
||||
const response = await fetch(
|
||||
'https://social.ayco.io/api/v1/accounts/lookup?acct=ayo'
|
||||
'https://m.webtoo.ls/api/v1/accounts/lookup?acct=ayo'
|
||||
)
|
||||
const data = await response.json()
|
||||
const { avatar } = data
|
||||
|
|
|
|||
|
|
@ -36,8 +36,9 @@ import Footer from '../components/Footer.astro'
|
|||
<p>
|
||||
In my spare time, I find it fun building <a href="/showcase">projects</a>,
|
||||
running self-hosted services at <a href="https://ayo.run">ayo.run</a>, and
|
||||
volunteering to <a href="https://ayos.blog/why-fediverse/" target="_blank"
|
||||
>Fediverse</a
|
||||
volunteering to <a
|
||||
href="https://v1.ayos.blog/why-fediverse/"
|
||||
target="_blank">Fediverse</a
|
||||
> projects like <a href="https://elk.zone">elk.zone</a>,
|
||||
<a href="https://m.webtoo.ls/public/local">webtoo.ls</a>, and <a
|
||||
href="https://m.webtoo.ls/@vitest">vitest's fedi presence</a
|
||||
|
|
@ -52,11 +53,9 @@ import Footer from '../components/Footer.astro'
|
|||
<h2 id="contact">Contact info</h2>
|
||||
<p>My inbox is open to everyone.</p>
|
||||
<ul>
|
||||
<li>✉️ Email me: <a href="mailto:hi@ayo.run">hi@ayo.run</a></li>
|
||||
<li>
|
||||
💬 Let's chat: <a href="https://chat.ayo.run/join/7IKG-h3nW-pD1H"
|
||||
>chat.ayo.run</a
|
||||
>
|
||||
✉️ Email me: <a href="mailto:ayo@ayco.io">ayo@ayco.io</a> ·
|
||||
<small> (<a href="/pgp">PGP key</a>)</small>
|
||||
</li>
|
||||
<li>
|
||||
💬 Signal: <a
|
||||
|
|
@ -68,11 +67,11 @@ import Footer from '../components/Footer.astro'
|
|||
</ul>
|
||||
</main>
|
||||
<Footer />
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
</style>
|
||||
</Layout>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Picture } from 'astro:assets'
|
|||
|
||||
// fetch mastodon account
|
||||
const response = await fetch(
|
||||
'https://social.ayco.io/api/v1/accounts/lookup?acct=ayo'
|
||||
'https://m.webtoo.ls/api/v1/accounts/lookup?acct=ayo'
|
||||
)
|
||||
const data = await response.json()
|
||||
const { avatar, note } = data
|
||||
|
|
@ -41,15 +41,6 @@ const avatarSize = 150
|
|||
<span class="now-label">now</span>
|
||||
<span class="status">{now.title}</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://chat.ayo.run/join/7IKG-h3nW-pD1H"
|
||||
class="chat-link action"
|
||||
>
|
||||
<status-indicator id="chat-link" pulse status="positive">
|
||||
Chat
|
||||
</status-indicator>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -59,9 +50,6 @@ const avatarSize = 150
|
|||
I care about the <em>Web</em>, and I love to <em>create</em> stuff to <em
|
||||
>inspire</em
|
||||
> and <em>serve</em> others.
|
||||
<!--
|
||||
<a href="/about">More?</a>
|
||||
-->
|
||||
</p>
|
||||
</section>
|
||||
<section class="cards-section">
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ publishedOn = publishedOn === '' ? publishDate : publishedOn
|
|||
</p>
|
||||
|
||||
<Fragment set:html={content} />
|
||||
|
||||
</main>
|
||||
<Footer />
|
||||
</Layout>
|
||||
|
|
|
|||
132
src/pages/pgp.astro
Normal file
132
src/pages/pgp.astro
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro'
|
||||
import Footer from '../components/Footer.astro'
|
||||
|
||||
const title = 'PGP public key'
|
||||
const description =
|
||||
'Use to verify my digital signature or to encrypt messages intended only for me.'
|
||||
---
|
||||
|
||||
<Layout title={"Ayo's " + title} description={description}>
|
||||
<main>
|
||||
<h1>My {title}</h1>
|
||||
<p>{description}</p>
|
||||
|
||||
<div class="key-block" role="region" aria-labelledby="public-key">
|
||||
<div class="btn-wrapper">
|
||||
<button class="copy-btn btn" aria-label="Copy key to clipboard"
|
||||
>Copy</button
|
||||
>
|
||||
<a href="/publickey.asc" class="btn">Download</a>
|
||||
</div>
|
||||
<pre
|
||||
id="public-key"><code>
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mDMEahs0NhYJKwYBBAHaRw8BAQdAV2CfblniKxklPgW9eYt2gBl0jMHLwtjrQaY+
|
||||
BQoWdIa0FkF5byBBeWNvIDxheW9AYXljby5pbz6ImQQTFgoAQRYhBBfxPV6P9zcr
|
||||
E1RcOGXmv2QVKTxlBQJqGzQ2AhsDBQkB4TOABQsJCAcCAiICBhUKCQgLAgQWAgMB
|
||||
Ah4HAheAAAoJEGXmv2QVKTxlIeYA/2WLvkDapBbVmGXoACAhqcTN93/CoPyzUbhN
|
||||
hHE6mmAUAQDHsgCHmh3S/Rn4NRE3Gb41kiPTBWHrlYLTj3Kiw0ASB7g4BGobNDYS
|
||||
CisGAQQBl1UBBQEBB0C6OEKEIPLaNDOM6JYhvvq0Q4Mk/B1eyZBKF/b4fQvlGgMB
|
||||
CAeIfgQYFgoAJhYhBBfxPV6P9zcrE1RcOGXmv2QVKTxlBQJqGzQ2AhsMBQkB4TOA
|
||||
AAoJEGXmv2QVKTxlMSQBAP5ta1kUFp3HAYwcun8qmoiVq1dEJSN1LnI7HlX4ucTl
|
||||
AP0YLC768PFTBm9CM5T1BE0xjJ7s4dZSrVoI4n8RSe1nCA==
|
||||
=MTsv
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
</code></pre>
|
||||
</div>
|
||||
<p>Expiry Date: 2027-05-30</p>
|
||||
<p>
|
||||
Fingerprint: <code>17F1 3D5E 8FF7 372B 1354 5C38 65E6 BF64 1529 3C65</code
|
||||
>
|
||||
</p>
|
||||
|
||||
<p></p>
|
||||
</main>
|
||||
<Footer />
|
||||
</Layout>
|
||||
|
||||
<script>
|
||||
/* Clipboard copy logic */
|
||||
const copyBtn = document.querySelector('.copy-btn')
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', async () => {
|
||||
const keyText = (
|
||||
document.querySelector('#public-key code') as HTMLElement
|
||||
)?.innerText.trim()
|
||||
if (!keyText) return
|
||||
try {
|
||||
await navigator.clipboard.writeText(keyText)
|
||||
const btn = document.querySelector('.copy-btn')
|
||||
if (btn) {
|
||||
const original = btn.textContent
|
||||
btn.textContent = 'Copied!'
|
||||
setTimeout(() => {
|
||||
btn.textContent = original
|
||||
}, 2000)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Copy failed', err)
|
||||
alert('Unable to copy the key. Please copy it manually.')
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
code {
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.key-block {
|
||||
position: relative;
|
||||
background: #272822;
|
||||
color: #f8f8f2;
|
||||
font-family: monospace;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.4;
|
||||
padding: 1rem 1rem 1rem 1.5rem;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.key-block code {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
.btn-wrapper {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
background: var(--color-brand-blue-1);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 0.3rem 0.6rem;
|
||||
font-size: 0.8rem;
|
||||
cursor: pointer;
|
||||
opacity: 0.9;
|
||||
transition: opacity 0.2s;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:hover,
|
||||
.btn:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.btn:focus {
|
||||
outline: 2px solid #0056b3;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -11,8 +11,8 @@ import Card from '../components/Card.astro'
|
|||
<main>
|
||||
<h1><span class="text-gradient">Hobby Projects</span></h1>
|
||||
<p>
|
||||
See more of my previous projects at <a href="https://ayos.blog"
|
||||
>my blog</a
|
||||
See more of my previous projects at <a
|
||||
href="https://v1.ayos.blog/projects">my blog</a
|
||||
>.
|
||||
</p>
|
||||
<ul>
|
||||
|
|
|
|||
121
tests/prep-now.test.ts
Normal file
121
tests/prep-now.test.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import { readFileSync, writeFileSync, copyFileSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { consola } from 'consola'
|
||||
|
||||
import newNow from '../commands/prep-now'
|
||||
|
||||
// Mock file system operations
|
||||
vi.mock('path', () => ({
|
||||
resolve: vi.fn(),
|
||||
readFileSync: vi.fn(),
|
||||
writeFileSync: vi.fn(),
|
||||
copyFileSync: vi.fn(),
|
||||
}))
|
||||
|
||||
// Mock consola
|
||||
vi.mock('consola', () => ({
|
||||
consola: {
|
||||
box: vi.fn(),
|
||||
start: vi.fn(),
|
||||
success: vi.fn(),
|
||||
fail: vi.fn(),
|
||||
error: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
// Mock mdToHTML
|
||||
vi.mock('../command/md-to-html', () => ({
|
||||
mdToHTML: vi.fn(),
|
||||
}))
|
||||
|
||||
describe('prep-now', () => {
|
||||
// const mockNow = {
|
||||
// title: 'Test Title',
|
||||
// description: 'Test Description',
|
||||
// publishedOn: '2023-01-01',
|
||||
// publishDate: '2023-01-01',
|
||||
// publishState: 'draft',
|
||||
// content: '# Test Content',
|
||||
// }
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
vi.mocked(resolve).mockImplementation((...paths) => paths.join('/'))
|
||||
vi.mocked(readFileSync).mockReturnValue('template content')
|
||||
vi.mocked(writeFileSync).mockImplementation(() => {})
|
||||
vi.mocked(copyFileSync).mockImplementation(() => {})
|
||||
vi.mocked(consola.box).mockImplementation(() => {})
|
||||
vi.mocked(consola.start).mockImplementation(() => {})
|
||||
vi.mocked(consola.success).mockImplementation(() => {})
|
||||
vi.mocked(consola.fail).mockImplementation(() => {})
|
||||
vi.mocked(consola.error).mockImplementation(() => {})
|
||||
})
|
||||
|
||||
it('should create a new now page and clear the original files', async () => {
|
||||
// Mock the mdToHTML function
|
||||
const { mdToHTML } = await import('../utils/md-to-html')
|
||||
vi.mocked(mdToHTML).mockResolvedValue('<h1>Test Content</h1>')
|
||||
|
||||
// Mock file paths
|
||||
vi.mocked(resolve)
|
||||
.mockReturnValueOnce('/src/constants/now.md')
|
||||
.mockReturnValueOnce('/src/constants/now.json')
|
||||
.mockReturnValueOnce('/src/pages/now/and-then/posts/2023-01-01.astro')
|
||||
.mockReturnValueOnce('/src/constants/bkup/2023-01-01.md')
|
||||
.mockReturnValueOnce('/src/constants/bkup/2023-01-01.json')
|
||||
|
||||
// Mock file content
|
||||
vi.mocked(readFileSync)
|
||||
.mockReturnValueOnce('template content')
|
||||
.mockReturnValueOnce('# Test Content')
|
||||
|
||||
// Mock file paths
|
||||
const __filename = '/src/commands/prep-now.ts'
|
||||
const __dirname = '/src/commands'
|
||||
vi.mocked(fileURLToPath).mockReturnValue(__filename)
|
||||
vi.mocked(dirname).mockReturnValue(__dirname)
|
||||
|
||||
// Execute the function
|
||||
await newNow()
|
||||
|
||||
// Verify file operations
|
||||
expect(writeFileSync).toHaveBeenCalledTimes(2)
|
||||
expect(copyFileSync).toHaveBeenCalledTimes(2)
|
||||
expect(consola.success).toHaveBeenCalledWith('now.md cleared')
|
||||
expect(consola.success).toHaveBeenCalledWith(
|
||||
'You may now update your Now content and props.\n'
|
||||
)
|
||||
})
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
// Mock an error
|
||||
vi.mocked(writeFileSync).mockImplementation(() => {
|
||||
throw new Error('Write failed')
|
||||
})
|
||||
|
||||
// Mock file paths
|
||||
vi.mocked(resolve)
|
||||
.mockReturnValueOnce('/src/constants/now.md')
|
||||
.mockReturnValueOnce('/src/constants/now.json')
|
||||
.mockReturnValueOnce('/src/pages/now/and-then/posts/2023-01-01.astro')
|
||||
.mockReturnValueOnce('/src/constants/bkup/2023-01-01.md')
|
||||
.mockReturnValueOnce('/src/constants/bkup/2023-01-01.json')
|
||||
|
||||
// Mock file content
|
||||
vi.mocked(readFileSync)
|
||||
.mockReturnValueOnce('template content')
|
||||
.mockReturnValueOnce('# Test Content')
|
||||
|
||||
// Execute the function
|
||||
await newNow()
|
||||
|
||||
// Verify error handling
|
||||
expect(consola.fail).toHaveBeenCalledWith(
|
||||
'Failed to create a new post from Now'
|
||||
)
|
||||
expect(consola.error).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
91
tests/sw.test.js
Normal file
91
tests/sw.test.js
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { install } from 'vitest-dom'
|
||||
|
||||
// Install DOM environment for vitest
|
||||
install()
|
||||
|
||||
// Mock the service worker globals
|
||||
global.caches = {
|
||||
keys: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
open: vi.fn(),
|
||||
match: vi.fn(),
|
||||
}
|
||||
|
||||
// Mock the global self object
|
||||
global.self = {
|
||||
skipWaiting: vi.fn(),
|
||||
addEventListener: vi.fn(),
|
||||
}
|
||||
|
||||
// Mock the fetch function
|
||||
global.fetch = vi.fn()
|
||||
|
||||
// Import the service worker module
|
||||
// Note: We need to use dynamic import to avoid module loading issues
|
||||
let swModule
|
||||
|
||||
beforeEach(async () => {
|
||||
// Clear all mocks
|
||||
vi.clearAllMocks()
|
||||
|
||||
// Mock the module
|
||||
swModule = await import('../src/sw.mjs')
|
||||
})
|
||||
|
||||
describe('Service Worker', () => {
|
||||
describe('cleanOldCaches', () => {
|
||||
it('should delete old caches', async () => {
|
||||
const cacheName = 'app-v000'
|
||||
const oldCacheName = 'app-v001'
|
||||
|
||||
global.caches.keys.mockResolvedValue([cacheName, oldCacheName])
|
||||
global.caches.delete.mockResolvedValue(true)
|
||||
|
||||
await swModule.cleanOldCaches()
|
||||
|
||||
expect(global.caches.delete).toHaveBeenCalledWith(oldCacheName)
|
||||
})
|
||||
})
|
||||
|
||||
describe('addResourcesToCache', () => {
|
||||
it('should add resources to cache', async () => {
|
||||
const resources = ['/index.html', '/style.css']
|
||||
const cache = { addAll: vi.fn() }
|
||||
|
||||
global.caches.open.mockResolvedValue(cache)
|
||||
|
||||
await swModule.addResourcesToCache(resources)
|
||||
|
||||
expect(cache.addAll).toHaveBeenCalledWith(resources)
|
||||
})
|
||||
})
|
||||
|
||||
describe('networkFirst', () => {
|
||||
it('should return network response when available', async () => {
|
||||
const request = new Request('/test')
|
||||
const networkResponse = new Response('network content')
|
||||
|
||||
global.fetch.mockResolvedValue(networkResponse)
|
||||
global.caches.open.mockResolvedValue({ put: vi.fn() })
|
||||
|
||||
const result = await swModule.networkFirst({ request })
|
||||
|
||||
expect(result).toEqual(networkResponse)
|
||||
})
|
||||
|
||||
it('should return cached response when network fails', async () => {
|
||||
const request = new Request('/test')
|
||||
const cachedResponse = new Response('cached content')
|
||||
|
||||
global.fetch.mockRejectedValue(new Error('Network error'))
|
||||
global.caches.open.mockResolvedValue({
|
||||
match: vi.fn().mockResolvedValue(cachedResponse),
|
||||
})
|
||||
|
||||
const result = await swModule.networkFirst({ request })
|
||||
|
||||
expect(result).toEqual(cachedResponse)
|
||||
})
|
||||
})
|
||||
})
|
||||
14
vitest.config.ts
Normal file
14
vitest.config.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
// Exclude generated files and heavy folders from the watcher to avoid
|
||||
// continuous re-runs when build output or other tools touch files.
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
exclude: ['dist/**', 'public/**', 'node_modules/**'],
|
||||
},
|
||||
watch: {
|
||||
exclude: ['dist/**', 'public/**', 'node_modules/**', '.git/**'],
|
||||
},
|
||||
})
|
||||
Loading…
Reference in a new issue