fix: typsecript errors

This commit is contained in:
kolaente 2024-06-27 17:07:03 +02:00
parent 7c83fa2b23
commit 56fa212fc2
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
15 changed files with 332 additions and 122 deletions

View File

@ -1,11 +1,20 @@
import { defineConfig } from 'astro/config';
import tailwind from "@astrojs/tailwind";
import markdoc from "@astrojs/markdoc";
import cloudflare from "@astrojs/cloudflare";
import {defineConfig, envField} from 'astro/config'
import tailwind from '@astrojs/tailwind'
import markdoc from '@astrojs/markdoc'
import cloudflare from '@astrojs/cloudflare'
// import node from '@astrojs/node'
// https://astro.build/config
export default defineConfig({
output: 'hybrid',
integrations: [tailwind(), markdoc()],
adapter: cloudflare()
});
output: 'hybrid',
integrations: [tailwind(), markdoc()],
adapter: cloudflare(),
experimental: {
env: {
schema: {
TURNSTILE_SECRET: envField.string({context: 'server', access: 'secret'}),
},
},
},
})

View File

@ -13,6 +13,7 @@
"@astrojs/check": "^0.7.0",
"@astrojs/cloudflare": "^11.0.1",
"@astrojs/markdoc": "^0.11.0",
"@astrojs/node": "^8.3.2",
"@astrojs/tailwind": "^5.1.0",
"@fontsource/open-sans": "^5.0.28",
"@fontsource/quicksand": "^5.0.18",

160
pnpm-lock.yaml generated
View File

@ -17,6 +17,9 @@ importers:
'@astrojs/markdoc':
specifier: ^0.11.0
version: 0.11.0(astro@4.10.3(@types/node@20.14.9)(typescript@5.4.5))
'@astrojs/node':
specifier: ^8.3.2
version: 8.3.2(astro@4.10.3(@types/node@20.14.9)(typescript@5.4.5))
'@astrojs/tailwind':
specifier: ^5.1.0
version: 5.1.0(astro@4.10.3(@types/node@20.14.9)(typescript@5.4.5))(tailwindcss@3.4.4)
@ -96,6 +99,11 @@ packages:
'@astrojs/markdown-remark@5.1.0':
resolution: {integrity: sha512-S6Z3K2hOB7MfjeDoHsotnP/q2UsnEDB8NlNAaCjMDsGBZfTUbWxyLW3CaphEWw08f6KLZi2ibK9yC3BaMhh2NQ==}
'@astrojs/node@8.3.2':
resolution: {integrity: sha512-Upv0D+9b3RXp7XViQTtrijaDqihHWbVHLdJQ2sxtPOEtw2GDrVxuC6LmXIUew5YvJ9Ylmpst6KizVwO8d/K9/Q==}
peerDependencies:
astro: ^4.2.0
'@astrojs/prism@3.1.0':
resolution: {integrity: sha512-Z9IYjuXSArkAUx3N6xj6+Bnvx8OdUSHA8YoOgyepp3+zJmtVYJIl/I18GozdJVW1p5u/CNpl3Km7/gwTJK85cw==}
engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0}
@ -1433,6 +1441,14 @@ packages:
date-fns@3.6.0:
resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==}
debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
debug@4.3.5:
resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==}
engines: {node: '>=6.0'}
@ -1448,10 +1464,18 @@ packages:
defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
destroy@1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
detect-libc@2.0.3:
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
engines: {node: '>=8'}
@ -1496,6 +1520,9 @@ packages:
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
electron-to-chromium@1.4.806:
resolution: {integrity: sha512-nkoEX2QIB8kwCOtvtgwhXWy2IHVcOLQZu9Qo36uaGB835mdX/h8uLRlosL6QIhLVUnAiicXRW00PwaPZC74Nrg==}
@ -1511,6 +1538,10 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
encodeurl@1.0.2:
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
engines: {node: '>= 0.8'}
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@ -1542,6 +1573,9 @@ packages:
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
engines: {node: '>=6'}
escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
@ -1565,6 +1599,10 @@ packages:
estree-walker@3.0.3:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
etag@1.8.1:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
@ -1616,6 +1654,10 @@ packages:
fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
fresh@0.5.2:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@ -1729,6 +1771,10 @@ packages:
http-cache-semantics@4.1.1:
resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
http-errors@2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
human-signals@5.0.0:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'}
@ -1736,6 +1782,9 @@ packages:
import-meta-resolve@4.1.0:
resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==}
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
is-arrayish@0.3.2:
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
@ -2040,6 +2089,11 @@ packages:
resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
engines: {node: '>=8.6'}
mime@1.6.0:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
engines: {node: '>=4'}
hasBin: true
mime@3.0.0:
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
engines: {node: '>=10.0.0'}
@ -2074,9 +2128,15 @@ packages:
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
engines: {node: '>=10'}
ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
muggle-string@0.4.1:
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
@ -2125,6 +2185,10 @@ packages:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'}
onetime@5.1.2:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
@ -2295,6 +2359,10 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
range-parser@1.2.1:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'}
read-cache@1.0.0:
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
@ -2400,6 +2468,16 @@ packages:
engines: {node: '>=10'}
hasBin: true
send@0.18.0:
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
engines: {node: '>= 0.8.0'}
server-destroy@1.0.1:
resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==}
setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
sharp@0.33.4:
resolution: {integrity: sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==}
engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@ -2449,6 +2527,10 @@ packages:
stacktracey@2.1.8:
resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==}
statuses@2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
stdin-discarder@0.2.2:
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
engines: {node: '>=18'}
@ -2528,6 +2610,10 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
toidentifier@1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
@ -2979,6 +3065,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@astrojs/node@8.3.2(astro@4.10.3(@types/node@20.14.9)(typescript@5.4.5))':
dependencies:
astro: 4.10.3(@types/node@20.14.9)(typescript@5.4.5)
send: 0.18.0
server-destroy: 1.0.1
transitivePeerDependencies:
- supports-color
'@astrojs/prism@3.1.0':
dependencies:
prismjs: 1.29.0
@ -4118,6 +4212,10 @@ snapshots:
date-fns@3.6.0: {}
debug@2.6.9:
dependencies:
ms: 2.0.0
debug@4.3.5:
dependencies:
ms: 2.1.2
@ -4128,8 +4226,12 @@ snapshots:
defu@6.1.4: {}
depd@2.0.0: {}
dequal@2.0.3: {}
destroy@1.2.0: {}
detect-libc@2.0.3:
optional: true
@ -4171,6 +4273,8 @@ snapshots:
eastasianwidth@0.2.0: {}
ee-first@1.1.1: {}
electron-to-chromium@1.4.806: {}
emmet@2.4.7:
@ -4184,6 +4288,8 @@ snapshots:
emoji-regex@9.2.2: {}
encodeurl@1.0.2: {}
entities@4.5.0: {}
es-module-lexer@1.5.3: {}
@ -4293,6 +4399,8 @@ snapshots:
escalade@3.1.2: {}
escape-html@1.0.3: {}
escape-string-regexp@1.0.5: {}
escape-string-regexp@4.0.0: {}
@ -4307,6 +4415,8 @@ snapshots:
dependencies:
'@types/estree': 1.0.5
etag@1.8.1: {}
eventemitter3@5.0.1: {}
execa@8.0.1:
@ -4369,6 +4479,8 @@ snapshots:
fraction.js@4.3.7: {}
fresh@0.5.2: {}
fsevents@2.3.3:
optional: true
@ -4530,10 +4642,20 @@ snapshots:
http-cache-semantics@4.1.1: {}
http-errors@2.0.0:
dependencies:
depd: 2.0.0
inherits: 2.0.4
setprototypeof: 1.2.0
statuses: 2.0.1
toidentifier: 1.0.1
human-signals@5.0.0: {}
import-meta-resolve@4.1.0: {}
inherits@2.0.4: {}
is-arrayish@0.3.2:
optional: true
@ -4981,6 +5103,8 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
mime@1.6.0: {}
mime@3.0.0: {}
mimic-fn@2.1.0: {}
@ -5016,8 +5140,12 @@ snapshots:
mrmime@2.0.0: {}
ms@2.0.0: {}
ms@2.1.2: {}
ms@2.1.3: {}
muggle-string@0.4.1: {}
mustache@4.2.0: {}
@ -5052,6 +5180,10 @@ snapshots:
object-hash@3.0.0: {}
on-finished@2.4.1:
dependencies:
ee-first: 1.1.1
onetime@5.1.2:
dependencies:
mimic-fn: 2.1.0
@ -5208,6 +5340,8 @@ snapshots:
queue-microtask@1.2.3: {}
range-parser@1.2.1: {}
read-cache@1.0.0:
dependencies:
pify: 2.3.0
@ -5381,6 +5515,28 @@ snapshots:
semver@7.6.2: {}
send@0.18.0:
dependencies:
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
fresh: 0.5.2
http-errors: 2.0.0
mime: 1.6.0
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
statuses: 2.0.1
transitivePeerDependencies:
- supports-color
server-destroy@1.0.1: {}
setprototypeof@1.2.0: {}
sharp@0.33.4:
dependencies:
color: 4.2.3
@ -5444,6 +5600,8 @@ snapshots:
as-table: 1.0.55
get-source: 2.0.12
statuses@2.0.1: {}
stdin-discarder@0.2.2: {}
stoppable@1.1.0: {}
@ -5547,6 +5705,8 @@ snapshots:
dependencies:
is-number: 7.0.0
toidentifier@1.0.1: {}
trim-lines@3.0.1: {}
trough@2.2.0: {}

View File

@ -2,13 +2,14 @@
interface Props {
href?: string
class?: string
type?: 'submit' | 'button' | 'reset'
}
const {href, class: className} = Astro.props
const {href, class: className, type} = Astro.props
---
{href
? <a href={href} class={className}><slot/></a>
: <button type="button" class={className}><slot/></button>
: <button type="button" class={className} type={type || 'button'}><slot/></button>
}
<style>

View File

@ -1,7 +1,5 @@
---
import LogoFull from './LogoFull.astro'
import Button from './Button.astro'
import DarkModeSwitch from './partials/DarkModeSwitch.astro'
import SubscribeToNewsletter from './partials/SubscribeToNewsletter.astro'
const nowYear = (new Date()).getFullYear()
@ -212,7 +210,7 @@ const nowYear = (new Date()).getFullYear()
</footer>
<script>
function toggleMenu($target) {
function toggleMenu($target: HTMLElement) {
$target.classList.toggle('hidden')
const expanded = $target.getAttribute('aria-expanded')
$target.setAttribute('aria-expanded', expanded === 'false' ? 'true' : 'false')
@ -224,15 +222,21 @@ const nowYear = (new Date()).getFullYear()
0,
)
if ($navbarBurgers.length > 0) {
$navbarBurgers.forEach(function ($el) {
$navbarBurgers.forEach(function ($el: HTMLElement) {
const target = $el.dataset.target
if(!target) {
return
}
const $target = document.getElementById(target)
$el.addEventListener('click', function () {
toggleMenu($target)
})
$target.addEventListener('click', (el) => {
if (!$target) {
return
}
$target?.addEventListener('click', () => {
toggleMenu($target)
})
$el?.addEventListener('click', () => {
toggleMenu($target)
})
})
}
})

View File

@ -2,10 +2,10 @@
import NavItem from './NavItem.astro'
---
<button
id="navbar-burger"
class="block lg:hidden fixed top-2 right-2 cursor-pointer p-3 pr-4"
data-target="navbar-menu"
aria-label="Open Menu"
id="navbar-burger"
class="block lg:hidden fixed top-2 right-2 cursor-pointer p-3 pr-4"
data-target="navbar-menu"
aria-label="Open Menu"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-8">
<path fill-rule="evenodd"
@ -45,13 +45,15 @@ import NavItem from './NavItem.astro'
</div>
<script>
const navbar = document.getElementById('navbar-menu')
document.getElementById('navbar-burger').addEventListener('click', () => toggleMenu(navbar))
navbar.addEventListener('click', () => toggleMenu(navbar))
const navbar = document.getElementById('navbar-menu')
if (navbar) {
document.getElementById('navbar-burger')?.addEventListener('click', () => toggleMenu(navbar))
navbar?.addEventListener('click', () => toggleMenu(navbar))
}
function toggleMenu($target) {
$target.classList.toggle('hidden');
const expanded = $target.getAttribute('aria-expanded');
$target.setAttribute('aria-expanded', expanded === 'false' ? 'true' : 'false');
}
function toggleMenu($target: HTMLElement) {
$target.classList.toggle('hidden')
const expanded = $target.getAttribute('aria-expanded')
$target.setAttribute('aria-expanded', expanded === 'false' ? 'true' : 'false')
}
</script>

View File

@ -1,5 +1,13 @@
---
// TableOfContentsHeading.astro
interface Heading {
slug: string
text: string
subheadings: Heading[]
}
interface Props {
heading: Heading
}
const { heading } = Astro.props;
---

View File

@ -3,10 +3,10 @@
<svg class="dark:hidden block" xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M120,40V16a8,8,0,0,1,16,0V40a8,8,0,0,1-16,0Zm72,88a64,64,0,1,1-64-64A64.07,64.07,0,0,1,192,128Zm-16,0a48,48,0,1,0-48,48A48.05,48.05,0,0,0,176,128ZM58.34,69.66A8,8,0,0,0,69.66,58.34l-16-16A8,8,0,0,0,42.34,53.66Zm0,116.68-16,16a8,8,0,0,0,11.32,11.32l16-16a8,8,0,0,0-11.32-11.32ZM192,72a8,8,0,0,0,5.66-2.34l16-16a8,8,0,0,0-11.32-11.32l-16,16A8,8,0,0,0,192,72Zm5.66,114.34a8,8,0,0,0-11.32,11.32l16,16a8,8,0,0,0,11.32-11.32ZM48,128a8,8,0,0,0-8-8H16a8,8,0,0,0,0,16H40A8,8,0,0,0,48,128Zm80,80a8,8,0,0,0-8,8v24a8,8,0,0,0,16,0V216A8,8,0,0,0,128,208Zm112-88H216a8,8,0,0,0,0,16h24a8,8,0,0,0,0-16Z"></path></svg>
</button>
<script defer>
<script>
const button = document.getElementById('button-toggle-dark-mode')
button.addEventListener('click', () => {
button?.addEventListener('click', () => {
const isDark = document.documentElement.classList.contains('dark')
localStorage.theme = isDark ? 'light' : 'dark'
setThemeClass()

View File

@ -2,7 +2,7 @@
import Button from '../Button.astro'
interface Props {
showTitle: boolean
showTitle?: boolean
}
const {showTitle = true} = Astro.props

View File

@ -12,12 +12,12 @@ import Button from '../Button.astro'
<p>
<label for="newsletter-email" class="sr-only">E-mail</label>
<input
name="email"
required
type="email"
placeholder="Your E-mail address"
id="newsletter-email"
class="inline-flex relative justify-start items-center py-2 px-3 m-0 w-full max-w-full h-10 font-sans text-base leading-normal align-top bg-white rounded border border-solid appearance-none cursor-text border-gray-400 text-neutral-700"
name="email"
required
type="email"
placeholder="Your E-mail address"
id="newsletter-email"
class="inline-flex relative justify-start items-center py-2 px-3 m-0 w-full max-w-full h-10 font-sans text-base leading-normal align-top bg-white rounded border border-solid appearance-none cursor-text border-gray-400 text-neutral-700"
/>
</p>
@ -47,7 +47,7 @@ import Button from '../Button.astro'
const emailInput = document.getElementById('newsletter-email')
let scriptLoaded = false
emailInput.addEventListener('focus', function () {
emailInput?.addEventListener('focus', function () {
if (!scriptLoaded) {
const script = document.createElement('script')
script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js'
@ -61,35 +61,36 @@ import Button from '../Button.astro'
const errorMessage = document.getElementById('newsletter-error-message')
const successMessage = document.getElementById('newsletter-sign-up-success-message')
function showError(error) {
errorMessage.textContent = 'An error occurred. ' + error + ' Please try again.'
errorMessage.classList.remove('hidden')
console.error('Error during newsletter sign up:', error)
}
if (form && errorMessage && successMessage) {
function showError(error: string) {
if (errorMessage) {
errorMessage.textContent = 'An error occurred. ' + error + ' Please try again.'
errorMessage.classList.remove('hidden')
}
console.error('Error during newsletter sign up:', error)
}
form.addEventListener('submit', function (e) {
e.preventDefault()
form.addEventListener('submit', function (e) {
e.preventDefault()
const formData = new FormData(form)
const formData = new FormData(form as HTMLFormElement)
fetch('/api/newsletter-signup', {
method: 'POST',
body: formData,
fetch('/api/newsletter-signup', {
method: 'POST',
body: formData,
})
.then(response => {
if (!response.ok) {
return response.json().then(error => {
throw new Error(error)
})
}
errorMessage.classList.add('hidden')
successMessage.classList.toggle('hidden')
form.classList.add('hidden')
})
.catch(error => showError(error.message))
})
.then(response => {
if (!response.ok) {
return response.json().then(error => {
throw new Error(error)
})
}
return response.json()
})
.then(data => {
errorMessage.classList.add('hidden')
successMessage.classList.toggle('hidden')
form.classList.add('hidden')
})
.catch(error => showError(error.message))
})
}
</script>

1
src/env.d.ts vendored
View File

@ -1,2 +1,3 @@
/// <reference path="../.astro/env.d.ts" />
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View File

@ -1,5 +1,5 @@
---
import {MarkdownHeading} from 'astro'
import {type MarkdownHeading} from 'astro'
import {getCollection} from 'astro:content'
import Layout from './Layout.astro'
@ -11,12 +11,17 @@ interface Props {
headings: MarkdownHeading[]
}
interface MarkdownWithSubheadings extends MarkdownHeading {
subheadings: MarkdownWithSubheadings[]
}
const {title: originalTitle, headings} = Astro.props
// @ts-ignore: Property exists
const title = originalTitle ?? Astro.props.frontmatter?.title
// Taken from https://kld.dev/building-table-of-contents/
function buildToc(headings: MarkdownHeading[]) {
const toc = []
const toc: MarkdownWithSubheadings[] = []
const parentHeadings = new Map()
headings.forEach((h) => {
const heading = {...h, subheadings: []}
@ -32,44 +37,51 @@ function buildToc(headings: MarkdownHeading[]) {
const toc = buildToc(headings)
async function getSidebarNavigation() {
const docs = await getCollection('docs')
const entries = {}
docs.forEach(d => {
const groupKey = d.id.split('/')[0]
if (!entries[groupKey]) {
entries[groupKey] = []
}
if (d.data.hideInMenu) {
return
}
entries[groupKey].push({
url: '/docs/' + d.slug,
title: d.data.title,
})
})
const order = ['setup', 'usage', 'development']
const sortedData = order.reduce((obj, key) => {
if (entries[key]) {
obj[key] = entries[key].sort((a, b) => a.title.localeCompare(b.title))
}
return obj
}, {})
return Object.entries(sortedData)
interface SectionItem {
url: string;
title: string;
}
type DocumentationArray = [string, SectionItem[]][];
async function getSidebarNavigation(): Promise<DocumentationArray> {
const docs = await getCollection('docs')
const entries: { [key: string]: SectionItem[] } = {}
docs.forEach(d => {
const groupKey = d.id.split('/')[0]
if (!entries[groupKey]) {
entries[groupKey] = []
}
if (d.data.hideInMenu) {
return
}
entries[groupKey].push({
url: '/docs/' + d.slug,
title: d.data.title,
})
})
const order = ['setup', 'usage', 'development']
const sortedData = order.reduce((obj: { [key: string]: SectionItem[] }, key) => {
if (entries[key]) {
obj[key] = entries[key].sort((a: SectionItem, b: SectionItem) => a.title.localeCompare(b.title))
}
return obj
}, {})
return Object.entries(sortedData)
}
const sidebarEntries = await getSidebarNavigation()
---
<Layout title={title}>
<div class="mx-auto flex max-w-screen-2xl flex-col lg:flex-row lg:pt-8">
<button
class="navbar-burger m-2 mt-6 block lg:hidden rounded-sm bg-gray-200 py-2 px-1 text-center"
data-target="docsMenu"
class="navbar-burger m-2 mt-6 block lg:hidden rounded-sm bg-gray-200 py-2 px-1 text-center"
data-target="docsMenu"
>
Show Menu
</button>
@ -101,19 +113,20 @@ const sidebarEntries = await getSidebarNavigation()
</Prose>
</main>
<div class="w-full lg:w-1/5 pl-4 order-2 lg:order-3">
{toc.length > 0 &&
<div class="sticky top-2">
<div class="font-display font-bold">
On this page
</div>
<nav class="text-gray-600 dark:text-gray-300 pt-2 max-h-[calc(100vh-2rem)] overflow-y-auto overflow-x-hidden" id="toc">
<ul>
{toc.map((heading) =>
<TableOfContentsHeading heading={heading}/>)}
</ul>
</nav>
</div>
}
{toc.length > 0 &&
<div class="sticky top-2">
<div class="font-display font-bold">
On this page
</div>
<nav class="text-gray-600 dark:text-gray-300 pt-2 max-h-[calc(100vh-2rem)] overflow-y-auto overflow-x-hidden"
id="toc">
<ul>
{toc.map((heading) =>
<TableOfContentsHeading heading={heading}/>)}
</ul>
</nav>
</div>
}
</div>
</div>
</Layout>
@ -133,6 +146,7 @@ const sidebarEntries = await getSidebarNavigation()
// then iterate backwards, on the first match highlight it and break
for (let i = anchors.length - 1; i >= 0; i--) {
// @ts-ignore
if (scrollTop > anchors[i].offsetTop - 75) {
const link = document.querySelector(`nav ul li a[href="#${anchors[i].id}"]`)
if (link) link.classList.add('text-primary')

View File

@ -10,7 +10,7 @@ import Footer from '../components/Footer.astro'
import Header from '../components/Header.astro'
interface Props {
title: string;
type: 'text' | 'website';
type?: 'text' | 'website';
image?: string;
description?: string;
}
@ -50,11 +50,11 @@ const imageUrl = image
}
<!-- Links -->
<base href={Astro.url}/>
<link rel="canonical" href={Astro.url} itemprop="url"/>
<meta name="url" content={Astro.url}/>
<meta name="twitter:url" content={Astro.url}/>
<meta property="og:url" content={Astro.url}/>
<base href={Astro.url.toString()}/>
<link rel="canonical" href={Astro.url.toString()} itemprop="url"/>
<meta name="url" content={Astro.url.toString()}/>
<meta name="twitter:url" content={Astro.url.toString()}/>
<meta property="og:url" content={Astro.url.toString()}/>
<!-- Images -->
<meta itemprop="image" content={imageUrl}/>
@ -62,7 +62,7 @@ const imageUrl = image
<meta name="twitter:image" content={imageUrl}/>
<meta name="twitter:image:src" content={imageUrl}/>
<meta property="og:type" content={type}/>
<meta property="og:type" content={type || 'website'}/>
</head>
<body class="bg-gray-50 dark:bg-gray-900 font-sans text-gray-900 dark:text-gray-100 antialiased">

View File

@ -1,5 +1,5 @@
---
import {CollectionEntry, getCollection} from 'astro:content'
import {type CollectionEntry, getCollection} from 'astro:content'
import Docs from '../layouts/Docs.astro'
export async function getStaticPaths() {

View File

@ -1,6 +1,12 @@
import {TURNSTILE_SECRET} from 'astro:env/server'
const LIST_ID = 'f0bc9ec2-56a4-48c8-baad-7a31b137484e'
export async function POST({request}) {
interface FullRequestInput {
request: Request
}
export async function POST({request}: FullRequestInput) {
const body = await request.formData()
// Turnstile injects a token in "cf-turnstile-response".
@ -9,8 +15,10 @@ export async function POST({request}) {
// Validate the token by calling the "/siteverify" API.
let formData = new FormData()
formData.append('secret', env.TURNSTILE_SECRET)
formData.append('secret', TURNSTILE_SECRET)
// @ts-ignore
formData.append('response', token)
// @ts-ignore
formData.append('remoteip', ip)
const result = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
@ -24,6 +32,7 @@ export async function POST({request}) {
}
const subscribeData = new FormData()
// @ts-ignore
subscribeData.append('email', body.get('email'))
subscribeData.append('l', LIST_ID)