almost done

This commit is contained in:
Niccolo Borgioli 2024-11-29 17:58:26 +01:00
parent 44efa2047a
commit ccec3806f2
24 changed files with 479 additions and 106 deletions

3
TODO.md Normal file
View File

@ -0,0 +1,3 @@
- Search
- Tag count
- Link in contact to status monitor

View File

@ -1,17 +1,22 @@
// @ts-check // @ts-check
import { defineConfig } from 'astro/config' import { rehypeHeadingIds } from '@astrojs/markdown-remark'
import mdx from '@astrojs/mdx' import mdx from '@astrojs/mdx'
import sitemap from '@astrojs/sitemap' import sitemap from '@astrojs/sitemap'
import svelte from '@astrojs/svelte'
import { defineConfig } from 'astro/config'
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
import Icons from 'unplugin-icons/vite'
import { remarkReadingTime } from './readingTime' import { remarkReadingTime } from './readingTime'
import svelte from '@astrojs/svelte';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
site: 'https://example.com', site: 'https://example.com',
integrations: [mdx(), sitemap(), svelte()], integrations: [mdx(), sitemap(), svelte()],
markdown: { markdown: {
rehypePlugins: [rehypeHeadingIds, [rehypeAutolinkHeadings, { behavior: 'wrap' }]],
remarkPlugins: [remarkReadingTime], remarkPlugins: [remarkReadingTime],
}, },
vite: {
plugins: [Icons({ compiler: 'astro' })],
},
}) })

View File

@ -8,22 +8,26 @@
"preview": "astro preview", "preview": "astro preview",
"start": "astro dev" "start": "astro dev"
}, },
"dependencies": {},
"devDependencies": { "devDependencies": {
"@astrojs/check": "^0.9.4", "@astrojs/check": "^0.9.4",
"@astrojs/markdown-remark": "^5.3.0",
"@astrojs/mdx": "^3.1.9", "@astrojs/mdx": "^3.1.9",
"@astrojs/rss": "^4.0.9", "@astrojs/rss": "^4.0.9",
"@astrojs/sitemap": "^3.2.1", "@astrojs/sitemap": "^3.2.1",
"@astrojs/svelte": "^6.0.2", "@astrojs/svelte": "^6.0.2",
"@fontsource-variable/jost": "^5.1.1", "@fontsource-variable/jost": "^5.1.1",
"@fontsource-variable/playfair-display": "^5.1.0", "@fontsource-variable/playfair-display": "^5.1.0",
"@iconify-json/ion": "^1.2.1",
"astro": "^4.16.13", "astro": "^4.16.13",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"reading-time": "^1.5.0", "reading-time": "^1.5.0",
"rehype-autolink-headings": "^7.1.0",
"remark-toc": "^9.0.0",
"sass": "^1.81.0", "sass": "^1.81.0",
"sharp": "^0.33.5", "sharp": "^0.33.5",
"svelte": "^5.2.7", "svelte": "^5.2.7",
"typescript": "^5.6.3" "typescript": "^5.6.3",
"unplugin-icons": "^0.20.2"
}, },
"packageManager": "pnpm@9.12.3" "packageManager": "pnpm@9.12.3"
} }

212
pnpm-lock.yaml generated
View File

@ -11,6 +11,9 @@ importers:
'@astrojs/check': '@astrojs/check':
specifier: ^0.9.4 specifier: ^0.9.4
version: 0.9.4(typescript@5.6.3) version: 0.9.4(typescript@5.6.3)
'@astrojs/markdown-remark':
specifier: ^5.3.0
version: 5.3.0
'@astrojs/mdx': '@astrojs/mdx':
specifier: ^3.1.9 specifier: ^3.1.9
version: 3.1.9(astro@4.16.13(rollup@4.27.3)(sass@1.81.0)(stylus@0.64.0)(typescript@5.6.3)) version: 3.1.9(astro@4.16.13(rollup@4.27.3)(sass@1.81.0)(stylus@0.64.0)(typescript@5.6.3))
@ -29,6 +32,9 @@ importers:
'@fontsource-variable/playfair-display': '@fontsource-variable/playfair-display':
specifier: ^5.1.0 specifier: ^5.1.0
version: 5.1.0 version: 5.1.0
'@iconify-json/ion':
specifier: ^1.2.1
version: 1.2.1
astro: astro:
specifier: ^4.16.13 specifier: ^4.16.13
version: 4.16.13(rollup@4.27.3)(sass@1.81.0)(stylus@0.64.0)(typescript@5.6.3) version: 4.16.13(rollup@4.27.3)(sass@1.81.0)(stylus@0.64.0)(typescript@5.6.3)
@ -38,6 +44,12 @@ importers:
reading-time: reading-time:
specifier: ^1.5.0 specifier: ^1.5.0
version: 1.5.0 version: 1.5.0
rehype-autolink-headings:
specifier: ^7.1.0
version: 7.1.0
remark-toc:
specifier: ^9.0.0
version: 9.0.0
sass: sass:
specifier: ^1.81.0 specifier: ^1.81.0
version: 1.81.0 version: 1.81.0
@ -50,6 +62,9 @@ importers:
typescript: typescript:
specifier: ^5.6.3 specifier: ^5.6.3
version: 5.6.3 version: 5.6.3
unplugin-icons:
specifier: ^0.20.2
version: 0.20.2(svelte@5.2.7)
packages: packages:
@ -60,6 +75,15 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
'@antfu/install-pkg@0.4.1':
resolution: {integrity: sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==}
'@antfu/install-pkg@0.5.0':
resolution: {integrity: sha512-dKnk2xlAyC7rvTkpkHmu+Qy/2Zc3Vm/l8PtNyIOGDBtXPY3kThfU4ORNEp3V7SXw5XSOb+tOJaUYpfquPzL/Tg==}
'@antfu/utils@0.7.10':
resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
'@astrojs/check@0.9.4': '@astrojs/check@0.9.4':
resolution: {integrity: sha512-IOheHwCtpUfvogHHsvu0AbeRZEnjJg3MopdLddkJE70mULItS/Vh37BHcI00mcOJcH1vhD3odbpvWokpxam7xA==} resolution: {integrity: sha512-IOheHwCtpUfvogHHsvu0AbeRZEnjJg3MopdLddkJE70mULItS/Vh37BHcI00mcOJcH1vhD3odbpvWokpxam7xA==}
hasBin: true hasBin: true
@ -369,6 +393,15 @@ packages:
'@fontsource-variable/playfair-display@5.1.0': '@fontsource-variable/playfair-display@5.1.0':
resolution: {integrity: sha512-51UJAHznXiGkchEOT5AYFuIy9N9m1JE7YxcdOtY0H4SKgzK9YYGKpeCXv3dz2e1gAd+BP2TyR0QXNnVjgeCbgw==} resolution: {integrity: sha512-51UJAHznXiGkchEOT5AYFuIy9N9m1JE7YxcdOtY0H4SKgzK9YYGKpeCXv3dz2e1gAd+BP2TyR0QXNnVjgeCbgw==}
'@iconify-json/ion@1.2.1':
resolution: {integrity: sha512-33jiBdtP8+uBV0KRz8Z9g54QFujzssiT9W6wdNuY61VQM1s3cvoAX89yiczRs4/6b2xJE5vqqvsEJAQPqfY5JA==}
'@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
'@iconify/utils@2.1.33':
resolution: {integrity: sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==}
'@img/sharp-darwin-arm64@0.33.5': '@img/sharp-darwin-arm64@0.33.5':
resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@ -777,6 +810,9 @@ packages:
'@types/sax@1.2.7': '@types/sax@1.2.7':
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
'@types/ungap__structured-clone@1.2.0':
resolution: {integrity: sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==}
'@types/unist@2.0.11': '@types/unist@2.0.11':
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
@ -980,6 +1016,9 @@ packages:
common-ancestor-path@1.0.1: common-ancestor-path@1.0.1:
resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==}
confbox@0.1.8:
resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
convert-source-map@2.0.0: convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
@ -1226,6 +1265,9 @@ packages:
hast-util-from-parse5@8.0.2: hast-util-from-parse5@8.0.2:
resolution: {integrity: sha512-SfMzfdAi/zAoZ1KkFEyyeXBn7u/ShQrfd675ZEE9M3qj+PMFX05xubzRyF76CCSJu8au9jgVxDV1+okFvgZU4A==} resolution: {integrity: sha512-SfMzfdAi/zAoZ1KkFEyyeXBn7u/ShQrfd675ZEE9M3qj+PMFX05xubzRyF76CCSJu8au9jgVxDV1+okFvgZU4A==}
hast-util-heading-rank@3.0.0:
resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==}
hast-util-is-element@3.0.0: hast-util-is-element@3.0.0:
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
@ -1393,10 +1435,17 @@ packages:
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
kolorist@1.8.0:
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
load-yaml-file@0.2.0: load-yaml-file@0.2.0:
resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==}
engines: {node: '>=6'} engines: {node: '>=6'}
local-pkg@0.5.1:
resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==}
engines: {node: '>=14'}
locate-character@3.0.0: locate-character@3.0.0:
resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
@ -1487,6 +1536,9 @@ packages:
mdast-util-to-string@4.0.0: mdast-util-to-string@4.0.0:
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
mdast-util-toc@7.1.0:
resolution: {integrity: sha512-2TVKotOQzqdY7THOdn2gGzS9d1Sdd66bvxUyw3aNpWfcPXCLYSJCCgfPy30sEtuzkDraJgqF35dzgmz6xlvH/w==}
merge2@1.4.1: merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -1612,6 +1664,9 @@ packages:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
mlly@1.7.3:
resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==}
mrmime@2.0.0: mrmime@2.0.0:
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -1681,6 +1736,9 @@ packages:
package-json-from-dist@1.0.1: package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
package-manager-detector@0.2.5:
resolution: {integrity: sha512-3dS7y28uua+UDbRCLBqltMBrbI+A5U2mI9YuxHRxIWYmLj3DwntEBmERYzIAQ4DMeuCUOBSak7dBHHoXKpOTYQ==}
parse-entities@4.0.1: parse-entities@4.0.1:
resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==}
@ -1708,6 +1766,9 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'} engines: {node: '>=16 || 14 >=14.18'}
pathe@1.1.2:
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
picocolors@1.1.1: picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@ -1727,6 +1788,9 @@ packages:
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
pkg-types@1.2.1:
resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==}
postcss@8.4.49: postcss@8.4.49:
resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
@ -1782,6 +1846,9 @@ packages:
regex@5.0.2: regex@5.0.2:
resolution: {integrity: sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==} resolution: {integrity: sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==}
rehype-autolink-headings@7.1.0:
resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==}
rehype-parse@9.0.1: rehype-parse@9.0.1:
resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==} resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==}
@ -1816,6 +1883,9 @@ packages:
remark-stringify@11.0.0: remark-stringify@11.0.0:
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
remark-toc@9.0.0:
resolution: {integrity: sha512-KJ9txbo33GjDAV1baHFze7ij4G8c7SGYoY8Kzsm2gzFpbhL/bSoVpMMzGa3vrNDSWASNd/3ppAqL7cP2zD6JIA==}
request-light@0.5.8: request-light@0.5.8:
resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==} resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==}
@ -2026,6 +2096,9 @@ packages:
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
ufo@1.5.4:
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
unified@11.0.5: unified@11.0.5:
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
@ -2059,6 +2132,33 @@ packages:
unist-util-visit@5.0.0: unist-util-visit@5.0.0:
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
unplugin-icons@0.20.2:
resolution: {integrity: sha512-Ak6TKAiO812aIUrCelrBSTQbYC4FiqawnFrAusP/hjmB8f9cAug9jr381ItvLl+Asi4IVcjoOiPbpy9CfFGKvQ==}
peerDependencies:
'@svgr/core': '>=7.0.0'
'@svgx/core': ^1.0.1
'@vue/compiler-sfc': ^3.0.2 || ^2.7.0
svelte: ^3.0.0 || ^4.0.0 || ^5.0.0
vue-template-compiler: ^2.6.12
vue-template-es2015-compiler: ^1.9.0
peerDependenciesMeta:
'@svgr/core':
optional: true
'@svgx/core':
optional: true
'@vue/compiler-sfc':
optional: true
svelte:
optional: true
vue-template-compiler:
optional: true
vue-template-es2015-compiler:
optional: true
unplugin@1.16.0:
resolution: {integrity: sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==}
engines: {node: '>=14.0.0'}
update-browserslist-db@1.1.1: update-browserslist-db@1.1.1:
resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
hasBin: true hasBin: true
@ -2222,6 +2322,9 @@ packages:
web-namespaces@2.0.1: web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
webpack-virtual-modules@0.6.2:
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
which-pm-runs@1.1.0: which-pm-runs@1.1.0:
resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -2316,6 +2419,18 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.5 '@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25 '@jridgewell/trace-mapping': 0.3.25
'@antfu/install-pkg@0.4.1':
dependencies:
package-manager-detector: 0.2.5
tinyexec: 0.3.1
'@antfu/install-pkg@0.5.0':
dependencies:
package-manager-detector: 0.2.5
tinyexec: 0.3.1
'@antfu/utils@0.7.10': {}
'@astrojs/check@0.9.4(typescript@5.6.3)': '@astrojs/check@0.9.4(typescript@5.6.3)':
dependencies: dependencies:
'@astrojs/language-server': 2.15.4(typescript@5.6.3) '@astrojs/language-server': 2.15.4(typescript@5.6.3)
@ -2668,6 +2783,24 @@ snapshots:
'@fontsource-variable/playfair-display@5.1.0': {} '@fontsource-variable/playfair-display@5.1.0': {}
'@iconify-json/ion@1.2.1':
dependencies:
'@iconify/types': 2.0.0
'@iconify/types@2.0.0': {}
'@iconify/utils@2.1.33':
dependencies:
'@antfu/install-pkg': 0.4.1
'@antfu/utils': 0.7.10
'@iconify/types': 2.0.0
debug: 4.3.7
kolorist: 1.8.0
local-pkg: 0.5.1
mlly: 1.7.3
transitivePeerDependencies:
- supports-color
'@img/sharp-darwin-arm64@0.33.5': '@img/sharp-darwin-arm64@0.33.5':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.0.4 '@img/sharp-libvips-darwin-arm64': 1.0.4
@ -3048,6 +3181,8 @@ snapshots:
dependencies: dependencies:
'@types/node': 17.0.45 '@types/node': 17.0.45
'@types/ungap__structured-clone@1.2.0': {}
'@types/unist@2.0.11': {} '@types/unist@2.0.11': {}
'@types/unist@3.0.3': {} '@types/unist@3.0.3': {}
@ -3324,6 +3459,8 @@ snapshots:
common-ancestor-path@1.0.1: {} common-ancestor-path@1.0.1: {}
confbox@0.1.8: {}
convert-source-map@2.0.0: {} convert-source-map@2.0.0: {}
cookie@0.7.2: {} cookie@0.7.2: {}
@ -3591,6 +3728,10 @@ snapshots:
vfile-location: 5.0.3 vfile-location: 5.0.3
web-namespaces: 2.0.1 web-namespaces: 2.0.1
hast-util-heading-rank@3.0.0:
dependencies:
'@types/hast': 3.0.4
hast-util-is-element@3.0.0: hast-util-is-element@3.0.0:
dependencies: dependencies:
'@types/hast': 3.0.4 '@types/hast': 3.0.4
@ -3797,6 +3938,8 @@ snapshots:
kleur@4.1.5: {} kleur@4.1.5: {}
kolorist@1.8.0: {}
load-yaml-file@0.2.0: load-yaml-file@0.2.0:
dependencies: dependencies:
graceful-fs: 4.2.11 graceful-fs: 4.2.11
@ -3804,6 +3947,11 @@ snapshots:
pify: 4.0.1 pify: 4.0.1
strip-bom: 3.0.0 strip-bom: 3.0.0
local-pkg@0.5.1:
dependencies:
mlly: 1.7.3
pkg-types: 1.2.1
locate-character@3.0.0: {} locate-character@3.0.0: {}
locate-path@5.0.0: locate-path@5.0.0:
@ -4013,6 +4161,16 @@ snapshots:
dependencies: dependencies:
'@types/mdast': 4.0.4 '@types/mdast': 4.0.4
mdast-util-toc@7.1.0:
dependencies:
'@types/mdast': 4.0.4
'@types/ungap__structured-clone': 1.2.0
'@ungap/structured-clone': 1.2.0
github-slugger: 2.0.0
mdast-util-to-string: 4.0.0
unist-util-is: 6.0.0
unist-util-visit: 5.0.0
merge2@1.4.1: {} merge2@1.4.1: {}
micromark-core-commonmark@2.0.2: micromark-core-commonmark@2.0.2:
@ -4296,6 +4454,13 @@ snapshots:
minipass@7.1.2: minipass@7.1.2:
optional: true optional: true
mlly@1.7.3:
dependencies:
acorn: 8.14.0
pathe: 1.1.2
pkg-types: 1.2.1
ufo: 1.5.4
mrmime@2.0.0: {} mrmime@2.0.0: {}
ms@2.1.3: {} ms@2.1.3: {}
@ -4366,6 +4531,8 @@ snapshots:
package-json-from-dist@1.0.1: package-json-from-dist@1.0.1:
optional: true optional: true
package-manager-detector@0.2.5: {}
parse-entities@4.0.1: parse-entities@4.0.1:
dependencies: dependencies:
'@types/unist': 2.0.11 '@types/unist': 2.0.11
@ -4408,6 +4575,8 @@ snapshots:
minipass: 7.1.2 minipass: 7.1.2
optional: true optional: true
pathe@1.1.2: {}
picocolors@1.1.1: {} picocolors@1.1.1: {}
picomatch@2.3.1: {} picomatch@2.3.1: {}
@ -4420,6 +4589,12 @@ snapshots:
dependencies: dependencies:
find-up: 4.1.0 find-up: 4.1.0
pkg-types@1.2.1:
dependencies:
confbox: 0.1.8
mlly: 1.7.3
pathe: 1.1.2
postcss@8.4.49: postcss@8.4.49:
dependencies: dependencies:
nanoid: 3.3.7 nanoid: 3.3.7
@ -4490,6 +4665,15 @@ snapshots:
dependencies: dependencies:
regex-utilities: 2.3.0 regex-utilities: 2.3.0
rehype-autolink-headings@7.1.0:
dependencies:
'@types/hast': 3.0.4
'@ungap/structured-clone': 1.2.0
hast-util-heading-rank: 3.0.0
hast-util-is-element: 3.0.0
unified: 11.0.5
unist-util-visit: 5.0.0
rehype-parse@9.0.1: rehype-parse@9.0.1:
dependencies: dependencies:
'@types/hast': 3.0.4 '@types/hast': 3.0.4
@ -4571,6 +4755,11 @@ snapshots:
mdast-util-to-markdown: 2.1.2 mdast-util-to-markdown: 2.1.2
unified: 11.0.5 unified: 11.0.5
remark-toc@9.0.0:
dependencies:
'@types/mdast': 4.0.4
mdast-util-toc: 7.1.0
request-light@0.5.8: {} request-light@0.5.8: {}
request-light@0.7.0: {} request-light@0.7.0: {}
@ -4834,6 +5023,8 @@ snapshots:
typescript@5.6.3: {} typescript@5.6.3: {}
ufo@1.5.4: {}
unified@11.0.5: unified@11.0.5:
dependencies: dependencies:
'@types/unist': 3.0.3 '@types/unist': 3.0.3
@ -4890,6 +5081,25 @@ snapshots:
unist-util-is: 6.0.0 unist-util-is: 6.0.0
unist-util-visit-parents: 6.0.1 unist-util-visit-parents: 6.0.1
unplugin-icons@0.20.2(svelte@5.2.7):
dependencies:
'@antfu/install-pkg': 0.5.0
'@antfu/utils': 0.7.10
'@iconify/utils': 2.1.33
debug: 4.3.7
kolorist: 1.8.0
local-pkg: 0.5.1
unplugin: 1.16.0
optionalDependencies:
svelte: 5.2.7
transitivePeerDependencies:
- supports-color
unplugin@1.16.0:
dependencies:
acorn: 8.14.0
webpack-virtual-modules: 0.6.2
update-browserslist-db@1.1.1(browserslist@4.24.2): update-browserslist-db@1.1.1(browserslist@4.24.2):
dependencies: dependencies:
browserslist: 4.24.2 browserslist: 4.24.2
@ -5036,6 +5246,8 @@ snapshots:
web-namespaces@2.0.1: {} web-namespaces@2.0.1: {}
webpack-virtual-modules@0.6.2: {}
which-pm-runs@1.1.0: {} which-pm-runs@1.1.0: {}
which-pm@3.0.0: which-pm@3.0.0:

View File

@ -3,7 +3,7 @@ import '@fontsource-variable/jost'
import '@fontsource-variable/playfair-display' import '@fontsource-variable/playfair-display'
import '../styles/preflight.css' import '../styles/preflight.css'
import '../styles/global.css' import '../styles/global.scss'
interface Props { interface Props {
image?: string image?: string
@ -44,3 +44,6 @@ const description = 'Welcome to my website!'
<meta property="twitter:title" content={title} /> <meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} /> <meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, Astro.url)} /> <meta property="twitter:image" content={new URL(image, Astro.url)} />
<script async defer src="https://spectare.nicco.io/unicorn.js" data-website-id="bc7525c5-6928-49e1-9255-aca296947def"
></script>

View File

@ -1,14 +1,14 @@
--- ---
interface Props { interface Props {
date: Date; date: Date
} }
const { date } = Astro.props; const { date } = Astro.props
--- ---
<time datetime={date.toISOString()}> <time datetime={date.toISOString()}>
{ {
date.toLocaleDateString('en-us', { date.toLocaleDateString(undefined, {
year: 'numeric', year: 'numeric',
month: 'short', month: 'short',
day: 'numeric', day: 'numeric',

View File

@ -0,0 +1,51 @@
---
import FingerPrint from '~icons/ion/finger-print'
import ChatBubbles from '~icons/ion/chatbubbles-outline'
import Mail from '~icons/ion/mail-outline'
import Heart from '~icons/ion/heart'
import Github from '~icons/ion/logo-github'
import Trending from '~icons/ion/trending-up'
const links: { label: string; url: string; icon: astroHTML.JSX.Element }[] = [
{ label: 'Say hi@nicco.io', url: 'mailto:hi@nicco.io', icon: Mail },
{ label: 'Chat on discord', url: 'https://discord.gg/wS7RpYTYd2', icon: ChatBubbles },
{ label: 'GitHub', url: 'https://github.com/cupcakearmy', icon: Github },
{ label: 'Support my work', url: 'https://github.com/sponsors/cupcakearmy', icon: Heart },
{ label: 'Traffic', url: 'https://spectare.nicco.io/share/HYgOcrlfHxGB9RAR/nicco.io', icon: Trending },
{ label: 'Privacy', url: '/privacy', icon: FingerPrint },
]
---
<ul>
{
links.map(({ label, url, icon: Icon }) => {
return (
<li>
<a href={url} target="_blank" rel="noopener noreferrer">
{Icon && <Icon />}
{label}
</a>
</li>
)
})
}
</ul>
<style lang="scss">
ul {
display: flex;
flex-direction: column;
gap: 1rem;
}
a {
display: flex;
gap: 0.5rem;
padding: 0.5rem 0;
transition: var(--animation);
&:hover {
transform: translateX(5%) scale(1.1);
}
}
</style>

View File

@ -5,7 +5,7 @@ const routes = [
{ name: 'About', href: '/about' }, { name: 'About', href: '/about' },
{ name: 'Projects', href: '/projects' }, { name: 'Projects', href: '/projects' },
{ name: 'Blog', href: '/blog' }, { name: 'Blog', href: '/blog' },
{ name: 'Contact', href: '/contact' }, { name: 'Rest', href: '/rest' },
] ]
--- ---

View File

@ -1,32 +1,28 @@
--- ---
import type { CollectionEntry } from 'astro:content' import type { CollectionEntry } from 'astro:content'
import type { ReadTimeResults } from 'reading-time'
import FormattedDate from './FormattedDate.astro' import FormattedDate from './FormattedDate.astro'
import ReadingTime from './ReadingTime.astro'
export type Props = { type Props = {
post: CollectionEntry<'blog'> readingTime: ReadTimeResults
full?: boolean } & Pick<CollectionEntry<'blog'>['data'], 'date' | 'updatedDate'>
}
const { post, full = false } = Astro.props const { updatedDate, date, readingTime } = Astro.props
const { remarkPluginFrontmatter } = await post.render()
--- ---
<div class="attributes"> <div class="attributes">
<div> <div class="estimation">
<FormattedDate date={post.data.date} /> <FormattedDate date={date} />
{ {
full && post.data.updatedDate && post.data.date !== post.data.updatedDate && ( updatedDate && date !== updatedDate && (
<> <div class="updated">
<br /> Updated: <FormattedDate date={updatedDate} />
<small> </div>
Last update: <FormattedDate date={post.data.updatedDate} />
</small>
</>
) )
} }
</div> </div>
<div>~ {remarkPluginFrontmatter.readingTime.minutes.toFixed(0)} min</div> <ReadingTime readingTime={readingTime} />
</div> </div>
<style> <style>
@ -36,4 +32,13 @@ const { remarkPluginFrontmatter } = await post.render()
font-weight: 400; font-weight: 400;
margin-top: -0.125em; margin-top: -0.125em;
} }
.estimation {
display: flex;
align-items: baseline;
gap: 0.5em;
}
.updated {
font-size: 0.75em;
font-style: italic;
}
</style> </style>

View File

@ -9,15 +9,20 @@ export type Props = {
} }
const { post } = Astro.props const { post } = Astro.props
const { remarkPluginFrontmatter } = await post.render()
--- ---
<section class:list={{ without: !post.data.coverImage }}> <section class:list={{ without: !post.data.coverImage }}>
{post.data.coverImage && <Picture src={post.data.coverImage} alt={'foo'} />} {post.data.coverImage && <Picture src={post.data.coverImage} alt={'foo'} />}
<PostAttributes {post} /> <PostAttributes
date={post.data.date}
updatedDate={post.data.updatedDate}
readingTime={remarkPluginFrontmatter.readingTime}
/>
<h2> <h2>
{post.data.title} {post.data.title}
</h2> </h2>
<Tags tags={post.data.tags.map((tag) => ({ count: 1, name: tag, href: `/tag/${tag}` }))} /> <Tags tags={post.data.tags.map((tag) => ({ name: tag, href: `/tag/${tag}` }))} />
</section> </section>
<style lang="scss"> <style lang="scss">

View File

@ -0,0 +1,9 @@
---
import type { ReadTimeResults } from 'reading-time'
type Props = { readingTime: ReadTimeResults }
const { readingTime } = Astro.props
---
<span>~ {readingTime.minutes.toFixed(0)} min</span>

View File

@ -33,6 +33,5 @@ const { letters, readable = false, even = false } = Astro.props
div.readable { div.readable {
letter-spacing: initial; letter-spacing: initial;
text-transform: initial; text-transform: initial;
font-size: 2.25rem;
} }
</style> </style>

View File

@ -2,7 +2,7 @@
export type Props = { export type Props = {
name: string name: string
href: string href: string
count: number count?: number
} }
const { name, href, count } = Astro.props const { name, href, count } = Astro.props
@ -11,7 +11,7 @@ const { name, href, count } = Astro.props
<a {href}> <a {href}>
<div> <div>
{name} {name}
<i>{count}</i> {count && <i>{count}</i>}
</div> </div>
</a> </a>

47
src/components/Toc.astro Normal file
View File

@ -0,0 +1,47 @@
---
import type { MarkdownHeading } from 'astro'
type Props = { headings: MarkdownHeading[] }
const { headings } = Astro.props
---
<div class="toc">
<b>Outline</b>
{
headings.map(({ slug, text, depth }) => (
<div style={`margin-left: ${depth - 2}rem;`}>
<span>▶</span>
<a href={`#${slug}`}>{text}</a>
</div>
))
}
</div>
<style>
.toc {
margin: 2rem 0;
@media (min-width: 70rem) {
margin: 0;
position: absolute;
left: 45rem;
width: calc(100vw - 50rem);
}
}
span {
font-size: 0.5em;
transform: translateY(-0.8em);
display: inline-block;
}
a {
height: 1.4em;
display: inline-block;
max-width: calc(100% - 1.5rem);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
</style>

View File

@ -16,18 +16,6 @@ Lets dive deeper 🤿.
I created a tiny [companion repository](https://github.com/cupcakearmy/blog-typescript-graphql) if you want to check out the code and try it out. I created a tiny [companion repository](https://github.com/cupcakearmy/blog-typescript-graphql) if you want to check out the code and try it out.
Or check out the [finished demo](https://blog-typescript-graphql.vercel.app/). Or check out the [finished demo](https://blog-typescript-graphql.vercel.app/).
<figure>
![](images/clayton-robbins-Ru09fQONJWo-unsplash-1024x683.jpg)
<figcaption>
Photo by [Clayton Robbins](https://unsplash.com/@claytonrobbins?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/@claytonrobbins?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
</figcaption>
</figure>
## Intro ## Intro
First we need to decide on what do we want (and probably need) First we need to decide on what do we want (and probably need)
@ -50,7 +38,7 @@ The setup will be be for VSCode. For that we first install the [GraphQL extensio
We need to add a `.graphqlrc.yml` file at the root with the following content: We need to add a `.graphqlrc.yml` file at the root with the following content:
``` ```yaml
schema: https://api.spacex.land/graphql/ schema: https://api.spacex.land/graphql/
``` ```
@ -68,7 +56,7 @@ We want to take our endpoint, generate types and queries from it that can then b
There is this amazing project called `@graphql-codegen` which is a collection of tools for helping you generating various things from GraphQL. Let's install: There is this amazing project called `@graphql-codegen` which is a collection of tools for helping you generating various things from GraphQL. Let's install:
``` ```bash
# Generators # Generators
pnpm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-graphql-request pnpm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-graphql-request
# For the SDK # For the SDK
@ -79,17 +67,17 @@ I will assume my GraphQL stuff will live under `./src/lib/gql`
We will create a top level configuration file to handle all of our generation step called `codegen.yaml`. Ignore the `config` option for now, I will explain that later We will create a top level configuration file to handle all of our generation step called `codegen.yaml`. Ignore the `config` option for now, I will explain that later
``` ```yaml
schema: https://api.spacex.land/graphql/ schema: https://api.spacex.land/graphql/
documents: "src/**/*.graphql" documents: 'src/**/*.graphql'
generates: generates:
./src/lib/gql/gen.ts: ./src/lib/gql/gen.ts:
plugins: plugins:
- "@graphql-codegen/typescript" - '@graphql-codegen/typescript'
- "@graphql-codegen/typescript-operations" - '@graphql-codegen/typescript-operations'
- "@graphql-codegen/typescript-graphql-request" - '@graphql-codegen/typescript-graphql-request'
config: config:
maybeValue: "T" maybeValue: 'T'
typesPrefix: GQL typesPrefix: GQL
immutableTypes: true immutableTypes: true
useTypeImports: true useTypeImports: true
@ -104,7 +92,7 @@ The property `schema` does not need an explanation.
Now let's create a `src/lib/gql/root.graphql` file and write some queries, all autocompleted of course! Now let's create a `src/lib/gql/root.graphql` file and write some queries, all autocompleted of course!
``` ```gql
query LaunchpadsMany { query LaunchpadsMany {
launchpads(limit: 10) { launchpads(limit: 10) {
id id
@ -131,7 +119,7 @@ query LaunchByYear($year: String!) {
### Let magic do it's thing ### Let magic do it's thing
``` ```bash
pnpm exec graphql-codegen pnpm exec graphql-codegen
``` ```
@ -139,7 +127,7 @@ This will look at all our custom queries and mutations and generate us a ready t
### Leverage the new SDK ### Leverage the new SDK
``` ```ts
// src/lib/gql/index.ts // src/lib/gql/index.ts
import { GraphQLClient } from 'graphql-request' import { GraphQLClient } from 'graphql-request'
@ -149,7 +137,7 @@ const client = new GraphQLClient('https://api.spacex.land/graphql/')
export const SDK = getSdk(client) export const SDK = getSdk(client)
``` ```
``` ```ts
import { SDK } from '$lib/gql' import { SDK } from '$lib/gql'
const data = await SDK.LaunchByYear({ year: '2021' }) const data = await SDK.LaunchByYear({ year: '2021' })
@ -157,7 +145,7 @@ const data = await SDK.LaunchByYear({ year: '2021' })
You can also use the generated types to explicitly set them You can also use the generated types to explicitly set them
``` ```ts
import { SDK } from '$lib/gql' import { SDK } from '$lib/gql'
import type { GQLLaunchByYearQuery } from '$lib/gql/gen' import type { GQLLaunchByYearQuery } from '$lib/gql/gen'
@ -170,7 +158,7 @@ Every thing is typed now, I can't pass a number to the `year` variable or use re
I promised I would come back to it at some point. I promised I would come back to it at some point.
``` ```yaml
schema: ... schema: ...
generates: generates:
... ...

View File

@ -1,6 +1,7 @@
--- ---
title: 'Leaving Nextcloud: From heaven to the depths of Seafile' title: 'Leaving Nextcloud: From heaven to the depths of Seafile'
date: '2021-03-23' date: '2021-03-23'
updatedDate: '2021-03-27'
categories: categories:
- 'general' - 'general'
tags: tags:

View File

@ -1,8 +1,8 @@
--- ---
title: "Why I love JS but sometimes I feel we shoot ourself in the foot." title: 'Why I love JS but sometimes I feel we shoot ourself in the foot.'
date: "2020-05-29" date: '2020-05-29'
categories: categories:
- "general" - 'general'
--- ---
Let's start by saying this: I absolutely love JS & Typescript, they are my favourite languages and I would not want to live without them. Let's start by saying this: I absolutely love JS & Typescript, they are my favourite languages and I would not want to live without them.
@ -19,7 +19,7 @@ So an economist might think: "Why is this bad? Competition is always good as it
What is the consequence of this? Many abandoned, half-finished packages that need to be rewritten every now and then only to be left unmaintained again. Let the cycle repeat itself... What is the consequence of this? Many abandoned, half-finished packages that need to be rewritten every now and then only to be left unmaintained again. Let the cycle repeat itself...
## Bundle work! Not disperse it ## Bundle work! Don't disperse it
What if instead of reinventing the wheel over and over again we tune the wheel we have so that it becomes the best, most versatile wheel for everyone. Fragmentation is always a huge amount of work and leads to half-backed projects that always have some downsides. From that downside a new project is born and again, the cycle continues. What if instead of reinventing the wheel over and over again we tune the wheel we have so that it becomes the best, most versatile wheel for everyone. Fragmentation is always a huge amount of work and leads to half-backed projects that always have some downsides. From that downside a new project is born and again, the cycle continues.

View File

@ -0,0 +1,6 @@
---
title: Projects
date: '2024-11-29'
---
To be filled :)

View File

@ -0,0 +1,7 @@
---
title: Rest
date: '2024-11-29'
---
import ContactLinks from '../../components/Links.astro'
<ContactLinks/>

View File

@ -1,36 +1,30 @@
--- ---
import type { CollectionEntry } from 'astro:content' import type { MarkdownHeading } from 'astro'
import FormattedDate from '../components/FormattedDate.astro'
import { Image } from 'astro:assets' import { Image } from 'astro:assets'
import Root from './Root.astro' import type { CollectionEntry } from 'astro:content'
import type { ReadTimeResults } from 'reading-time'
import PostAttributes from '../components/PostAttributes.astro'
import Tags from '../components/Tags.astro'
import Toc from '../components/Toc.astro'
import PageWithTitle from './PageWithTitle.astro'
type Props = CollectionEntry<'blog'>['data'] type Props = CollectionEntry<'blog'>['data'] & { headings: MarkdownHeading[]; readingTime: ReadTimeResults }
const { title, updatedDate, date, tags, coverImage } = Astro.props const { title, updatedDate, date, tags, coverImage, headings, readingTime } = Astro.props
--- ---
<Root> <PageWithTitle title={title} readable>
<article> <article>
<div class="hero-image"> <Toc {headings} />
<PostAttributes {date} {updatedDate} {readingTime} />
{coverImage && <Image width={1020} height={510} src={coverImage} alt="" />} {coverImage && <Image width={1020} height={510} src={coverImage} alt="" />}
</div> <Tags tags={tags.map((t) => ({ name: t, href: `/tag/${t}` }))} />
<div class="prose">
<div class="title">
<div class="date">
<FormattedDate date={date} />
{
updatedDate && (
<div class="last-updated-on">
Last updated on <FormattedDate date={updatedDate} />
</div>
)
}
</div>
<h1>{title}</h1>
{tags.map((tag) => <a href={`/tag/${tag}`}>{tag}</a>)}
<hr />
</div>
<slot /> <slot />
</div>
</article> </article>
</Root> </PageWithTitle>
<style>
img {
margin: 1rem 0;
}
</style>

View File

@ -11,9 +11,25 @@ export async function getStaticPaths() {
} }
const post = Astro.props const post = Astro.props
const { Content } = await post.render() const { Content, headings, remarkPluginFrontmatter } = await post.render()
--- ---
<BlogPost {...post.data}> <BlogPost {...post.data} {headings} readingTime={remarkPluginFrontmatter.readingTime}>
<Content /> <Content />
</BlogPost> </BlogPost>
<style>
:global(p) {
margin: 1rem 0;
}
:global(h2, h3, h4, h5, h6) {
--width: 0.125rem;
--offset: 0.25rem;
margin: 2rem 0 1rem;
margin: 3em 0 0;
border-left: var(--width) solid var(--clr-primary);
padding-left: var(--offset);
margin-left: calc((var(--width) + var(--offset)) * -1);
}
</style>

View File

@ -1,7 +1,7 @@
--- ---
import { getCollection } from 'astro:content' import { getCollection } from 'astro:content'
import PostList from '../../components/PostList.astro' import PostList from '../../components/PostList.astro'
import Root from '../../layouts/Root.astro' import PageWithTitle from '../../layouts/PageWithTitle.astro'
export async function getStaticPaths() { export async function getStaticPaths() {
const posts = await getCollection('blog') const posts = await getCollection('blog')
@ -22,7 +22,6 @@ const params = Astro.params
const { posts } = Astro.props const { posts } = Astro.props
--- ---
<Root> <PageWithTitle title={params.tag}>
<h1>{params.tag}</h1>
<PostList posts={posts} /> <PostList posts={posts} />
</Root> </PageWithTitle>

View File

@ -58,6 +58,13 @@ h6 {
line-height: 1.2; line-height: 1.2;
} }
h2 {
font-size: 1.5rem;
}
h3 {
font-size: 1.25rem;
}
p { p {
text-align: justify; text-align: justify;
line-height: 1.5; line-height: 1.5;
@ -72,7 +79,18 @@ a {
text-decoration: none; text-decoration: none;
} }
p a,
.toc a {
border-bottom: 0.125em solid var(--clr-primary);
}
svg { svg {
fill: currentColor; fill: currentColor;
height: auto; height: auto;
} }
pre {
padding: 1rem;
margin: 1rem 0;
display: block;
}

View File

@ -1,6 +1,7 @@
{ {
"extends": "astro/tsconfigs/strictest", "extends": "astro/tsconfigs/strictest",
"compilerOptions": { "compilerOptions": {
"strictNullChecks": true "strictNullChecks": true,
"types": ["unplugin-icons/types/astro"]
} }
} }