chore: layout
This commit is contained in:
parent
b9561ad2d0
commit
230dca64ca
27 changed files with 446 additions and 339 deletions
|
@ -8,10 +8,19 @@ import remarkEmoji from 'remark-emoji'
|
||||||
import remarkMath from 'remark-math'
|
import remarkMath from 'remark-math'
|
||||||
import remarkToc from 'remark-toc'
|
import remarkToc from 'remark-toc'
|
||||||
|
|
||||||
|
import react from '@astrojs/react'
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: 'https://astro-micro-academic.vercel.app',
|
site: 'https://astro-micro-academic.vercel.app',
|
||||||
integrations: [tailwind(), sitemap(), mdx()],
|
integrations: [
|
||||||
|
tailwind({
|
||||||
|
applyBaseStyles: false,
|
||||||
|
}),
|
||||||
|
sitemap(),
|
||||||
|
mdx(),
|
||||||
|
react(),
|
||||||
|
],
|
||||||
markdown: {
|
markdown: {
|
||||||
shikiConfig: {
|
shikiConfig: {
|
||||||
theme: 'css-variables',
|
theme: 'css-variables',
|
||||||
|
@ -19,5 +28,11 @@ export default defineConfig({
|
||||||
rehypePlugins: [rehypeHeadingIds, rehypeKatex],
|
rehypePlugins: [rehypeHeadingIds, rehypeKatex],
|
||||||
remarkPlugins: [remarkToc, remarkMath, remarkEmoji],
|
remarkPlugins: [remarkToc, remarkMath, remarkEmoji],
|
||||||
},
|
},
|
||||||
server: { port: 1234, host: true },
|
server: {
|
||||||
|
port: 1234,
|
||||||
|
host: true,
|
||||||
|
},
|
||||||
|
devToolbar: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
20
components.json
Normal file
20
components.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "new-york",
|
||||||
|
"rsc": false,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.ts",
|
||||||
|
"css": "src/styles/global.css",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
}
|
||||||
|
}
|
208
package-lock.json
generated
208
package-lock.json
generated
|
@ -11,20 +11,29 @@
|
||||||
"@astrojs/check": "^0.7.0",
|
"@astrojs/check": "^0.7.0",
|
||||||
"@astrojs/markdown-remark": "^5.2.0",
|
"@astrojs/markdown-remark": "^5.2.0",
|
||||||
"@astrojs/mdx": "^3.1.2",
|
"@astrojs/mdx": "^3.1.2",
|
||||||
|
"@astrojs/react": "^3.6.2",
|
||||||
"@astrojs/rss": "^4.0.7",
|
"@astrojs/rss": "^4.0.7",
|
||||||
"@astrojs/sitemap": "^3.1.6",
|
"@astrojs/sitemap": "^3.1.6",
|
||||||
"@astrojs/tailwind": "^5.1.0",
|
"@astrojs/tailwind": "^5.1.0",
|
||||||
"@fontsource/geist-mono": "^5.0.3",
|
"@fontsource/geist-mono": "^5.0.3",
|
||||||
"@fontsource/geist-sans": "^5.0.3",
|
"@fontsource/geist-sans": "^5.0.3",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
|
"@types/react": "^18.3.5",
|
||||||
|
"@types/react-dom": "^18.3.0",
|
||||||
"astro": "^4.11.3",
|
"astro": "^4.11.3",
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"lucide-react": "^0.439.0",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
"rehype-katex": "^7.0.0",
|
"rehype-katex": "^7.0.0",
|
||||||
"remark-emoji": "^5.0.1",
|
"remark-emoji": "^5.0.1",
|
||||||
"remark-math": "^6.0.0",
|
"remark-math": "^6.0.0",
|
||||||
"remark-toc": "^9.0.0",
|
"remark-toc": "^9.0.0",
|
||||||
"tailwind-merge": "^2.3.0",
|
"tailwind-merge": "^2.5.2",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"typescript": "^5.4.5"
|
"typescript": "^5.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -222,6 +231,24 @@
|
||||||
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@astrojs/react": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@astrojs/react/-/react-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-fK29lYI7zK/KG4ZBy956x4dmauZcZ18osFkuyGa8r3gmmCQa2NZ9XNu9WaVYEUm0j89f4Gii4tbxLoyM8nk2MA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
|
"ultrahtml": "^1.5.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "^17.0.50 || ^18.0.21",
|
||||||
|
"@types/react-dom": "^17.0.17 || ^18.0.6",
|
||||||
|
"react": "^17.0.2 || ^18.0.0 || ^19.0.0-beta",
|
||||||
|
"react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0-beta"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@astrojs/rss": {
|
"node_modules/@astrojs/rss": {
|
||||||
"version": "4.0.7",
|
"version": "4.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/@astrojs/rss/-/rss-4.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@astrojs/rss/-/rss-4.0.7.tgz",
|
||||||
|
@ -593,6 +620,34 @@
|
||||||
"@babel/core": "^7.0.0-0"
|
"@babel/core": "^7.0.0-0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/plugin-transform-react-jsx-self": {
|
||||||
|
"version": "7.24.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz",
|
||||||
|
"integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.24.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/plugin-transform-react-jsx-source": {
|
||||||
|
"version": "7.24.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz",
|
||||||
|
"integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.24.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@babel/template": {
|
||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz",
|
||||||
|
@ -1705,6 +1760,14 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-icons": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.x || ^17.x || ^18.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.18.1",
|
"version": "4.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz",
|
||||||
|
@ -2082,6 +2145,28 @@
|
||||||
"undici-types": "~5.26.4"
|
"undici-types": "~5.26.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/prop-types": {
|
||||||
|
"version": "15.7.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
|
||||||
|
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
|
||||||
|
},
|
||||||
|
"node_modules/@types/react": {
|
||||||
|
"version": "18.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz",
|
||||||
|
"integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/prop-types": "*",
|
||||||
|
"csstype": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/react-dom": {
|
||||||
|
"version": "18.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz",
|
||||||
|
"integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/sax": {
|
"node_modules/@types/sax": {
|
||||||
"version": "1.2.7",
|
"version": "1.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz",
|
||||||
|
@ -2108,6 +2193,24 @@
|
||||||
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
|
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/@vitejs/plugin-react": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/core": "^7.24.5",
|
||||||
|
"@babel/plugin-transform-react-jsx-self": "^7.24.5",
|
||||||
|
"@babel/plugin-transform-react-jsx-source": "^7.24.1",
|
||||||
|
"@types/babel__core": "^7.20.5",
|
||||||
|
"react-refresh": "^0.14.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.18.0 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vite": "^4.2.0 || ^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@volar/kit": {
|
"node_modules/@volar/kit": {
|
||||||
"version": "2.4.0-alpha.15",
|
"version": "2.4.0-alpha.15",
|
||||||
"resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.0-alpha.15.tgz",
|
"resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.0-alpha.15.tgz",
|
||||||
|
@ -2832,6 +2935,25 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/class-variance-authority": {
|
||||||
|
"version": "0.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz",
|
||||||
|
"integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==",
|
||||||
|
"dependencies": {
|
||||||
|
"clsx": "2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://joebell.co.uk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/class-variance-authority/node_modules/clsx": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cli-boxes": {
|
"node_modules/cli-boxes": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz",
|
||||||
|
@ -2980,7 +3102,6 @@
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
|
@ -3121,6 +3242,11 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/csstype": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.5",
|
"version": "4.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
||||||
|
@ -4619,6 +4745,17 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/loose-envify": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"loose-envify": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||||
|
@ -4628,6 +4765,14 @@
|
||||||
"yallist": "^3.0.2"
|
"yallist": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucide-react": {
|
||||||
|
"version": "0.439.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.439.0.tgz",
|
||||||
|
"integrity": "sha512-PafSWvDTpxdtNEndS2HIHxcNAbd54OaqSYJO90/b63rab2HWYqDbH194j0i82ZFdWOAcf0AHinRykXRRK2PJbw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.10",
|
"version": "0.30.10",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
|
||||||
|
@ -6693,6 +6838,37 @@
|
||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/react": {
|
||||||
|
"version": "18.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||||
|
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-dom": {
|
||||||
|
"version": "18.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
|
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.1.0",
|
||||||
|
"scheduler": "^0.23.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^18.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-refresh": {
|
||||||
|
"version": "0.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
||||||
|
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/read-cache": {
|
"node_modules/read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
|
@ -7161,6 +7337,14 @@
|
||||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/scheduler": {
|
||||||
|
"version": "0.23.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
||||||
|
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/section-matter": {
|
"node_modules/section-matter": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
||||||
|
@ -7586,10 +7770,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tailwind-merge": {
|
"node_modules/tailwind-merge": {
|
||||||
"version": "2.4.0",
|
"version": "2.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz",
|
||||||
"integrity": "sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A==",
|
"integrity": "sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg==",
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/dcastil"
|
"url": "https://github.com/sponsors/dcastil"
|
||||||
|
@ -7632,6 +7815,14 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tailwindcss-animate": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"tailwindcss": ">=3.0.0 || insiders"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tailwindcss/node_modules/glob-parent": {
|
"node_modules/tailwindcss/node_modules/glob-parent": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||||
|
@ -7801,6 +7992,11 @@
|
||||||
"semver": "^7.3.8"
|
"semver": "^7.3.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ultrahtml": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg=="
|
||||||
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "5.26.5",
|
"version": "5.26.5",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
|
|
11
package.json
11
package.json
|
@ -15,20 +15,29 @@
|
||||||
"@astrojs/check": "^0.7.0",
|
"@astrojs/check": "^0.7.0",
|
||||||
"@astrojs/markdown-remark": "^5.2.0",
|
"@astrojs/markdown-remark": "^5.2.0",
|
||||||
"@astrojs/mdx": "^3.1.2",
|
"@astrojs/mdx": "^3.1.2",
|
||||||
|
"@astrojs/react": "^3.6.2",
|
||||||
"@astrojs/rss": "^4.0.7",
|
"@astrojs/rss": "^4.0.7",
|
||||||
"@astrojs/sitemap": "^3.1.6",
|
"@astrojs/sitemap": "^3.1.6",
|
||||||
"@astrojs/tailwind": "^5.1.0",
|
"@astrojs/tailwind": "^5.1.0",
|
||||||
"@fontsource/geist-mono": "^5.0.3",
|
"@fontsource/geist-mono": "^5.0.3",
|
||||||
"@fontsource/geist-sans": "^5.0.3",
|
"@fontsource/geist-sans": "^5.0.3",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
|
"@types/react": "^18.3.5",
|
||||||
|
"@types/react-dom": "^18.3.0",
|
||||||
"astro": "^4.11.3",
|
"astro": "^4.11.3",
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"lucide-react": "^0.439.0",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
"rehype-katex": "^7.0.0",
|
"rehype-katex": "^7.0.0",
|
||||||
"remark-emoji": "^5.0.1",
|
"remark-emoji": "^5.0.1",
|
||||||
"remark-math": "^6.0.0",
|
"remark-math": "^6.0.0",
|
||||||
"remark-toc": "^9.0.0",
|
"remark-toc": "^9.0.0",
|
||||||
"tailwind-merge": "^2.3.0",
|
"tailwind-merge": "^2.5.2",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"typescript": "^5.4.5"
|
"typescript": "^5.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="mx-auto max-w-screen-md px-3"><slot /></div>
|
<div class="mx-auto max-w-screen-md"><slot /></div>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import BackToTop from '@components/BackToTop.astro'
|
||||||
import SocialIcons from './SocialIcons.astro'
|
import SocialIcons from './SocialIcons.astro'
|
||||||
---
|
---
|
||||||
|
|
||||||
<footer class="animate">
|
<footer>
|
||||||
<Container>
|
<Container>
|
||||||
<div class="my-2 flex justify-between">
|
<div class="my-2 flex justify-between">
|
||||||
<SocialIcons icon_size={'text-xl'} />
|
<SocialIcons icon_size={'text-xl'} />
|
||||||
|
@ -16,78 +16,6 @@ import SocialIcons from './SocialIcons.astro'
|
||||||
© {new Date().getFullYear()} • {SITE.TITLE} 👀<br />
|
© {new Date().getFullYear()} • {SITE.TITLE} 👀<br />
|
||||||
Built with Astro
|
Built with Astro
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap items-center gap-1.5">
|
|
||||||
<button
|
|
||||||
id="light-theme-button"
|
|
||||||
aria-label="Light theme"
|
|
||||||
class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="18"
|
|
||||||
height="18"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"
|
|
||||||
>
|
|
||||||
<circle cx="12" cy="12" r="5"></circle>
|
|
||||||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|
||||||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|
||||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|
||||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|
||||||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|
||||||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|
||||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|
||||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
id="dark-theme-button"
|
|
||||||
aria-label="Dark theme"
|
|
||||||
class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="18"
|
|
||||||
height="18"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"
|
|
||||||
>
|
|
||||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
id="system-theme-button"
|
|
||||||
aria-label="System theme"
|
|
||||||
class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="18"
|
|
||||||
height="18"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"
|
|
||||||
>
|
|
||||||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
|
|
||||||
<line x1="8" y1="21" x2="16" y2="21"></line>
|
|
||||||
<line x1="12" y1="17" x2="12" y2="21"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
---
|
---
|
||||||
import '../styles/global.css'
|
import '../styles/global.css'
|
||||||
import { ViewTransitions } from 'astro:transitions'
|
|
||||||
|
|
||||||
import '@fontsource/geist-sans'
|
import '@fontsource/geist-sans'
|
||||||
import '@fontsource/geist-mono'
|
import '@fontsource/geist-mono'
|
||||||
|
@ -16,46 +15,31 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site)
|
||||||
const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props
|
const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Global Metadata -->
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
||||||
<link
|
|
||||||
rel="icon"
|
|
||||||
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🍄</text></svg>"
|
|
||||||
/>
|
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
|
|
||||||
<!-- Canonical URL -->
|
|
||||||
<link rel="canonical" href={canonicalURL} />
|
<link rel="canonical" href={canonicalURL} />
|
||||||
|
|
||||||
<!-- Primary Meta Tags -->
|
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
<meta name="title" content={title} />
|
<meta name="title" content={title} />
|
||||||
<meta name="description" content={description} />
|
<meta name="description" content={description} />
|
||||||
|
|
||||||
<!-- Open Graph / Facebook -->
|
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:url" content={Astro.url} />
|
<meta property="og:url" content={Astro.url} />
|
||||||
<meta property="og:title" content={title} />
|
<meta property="og:title" content={title} />
|
||||||
<meta property="og:description" content={description} />
|
<meta property="og:description" content={description} />
|
||||||
<meta property="og:image" content={new URL(image, Astro.url)} />
|
<meta property="og:image" content={new URL(image, Astro.url)} />
|
||||||
|
|
||||||
<!-- Twitter -->
|
|
||||||
<meta property="twitter:card" content="summary_large_image" />
|
<meta property="twitter:card" content="summary_large_image" />
|
||||||
<meta property="twitter:url" content={Astro.url} />
|
<meta property="twitter:url" content={Astro.url} />
|
||||||
<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)} />
|
||||||
|
|
||||||
<ViewTransitions />
|
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
function init() {
|
function init() {
|
||||||
preloadTheme()
|
|
||||||
onScroll()
|
onScroll()
|
||||||
animate()
|
|
||||||
updateThemeButtons()
|
|
||||||
addCopyCodeButtons()
|
addCopyCodeButtons()
|
||||||
|
|
||||||
const backToTop = document.getElementById('back-to-top')
|
const backToTop = document.getElementById('back-to-top')
|
||||||
|
@ -64,77 +48,9 @@ const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props
|
||||||
const backToPrev = document.getElementById('back-to-prev')
|
const backToPrev = document.getElementById('back-to-prev')
|
||||||
backToPrev?.addEventListener('click', () => window.history.back())
|
backToPrev?.addEventListener('click', () => window.history.back())
|
||||||
|
|
||||||
const lightThemeButton = document.getElementById('light-theme-button')
|
|
||||||
lightThemeButton?.addEventListener('click', () => {
|
|
||||||
localStorage.setItem('theme', 'light')
|
|
||||||
toggleTheme(false)
|
|
||||||
updateThemeButtons()
|
|
||||||
})
|
|
||||||
|
|
||||||
const darkThemeButton = document.getElementById('dark-theme-button')
|
|
||||||
darkThemeButton?.addEventListener('click', () => {
|
|
||||||
localStorage.setItem('theme', 'dark')
|
|
||||||
toggleTheme(true)
|
|
||||||
updateThemeButtons()
|
|
||||||
})
|
|
||||||
|
|
||||||
const systemThemeButton = document.getElementById('system-theme-button')
|
|
||||||
systemThemeButton?.addEventListener('click', () => {
|
|
||||||
localStorage.setItem('theme', 'system')
|
|
||||||
toggleTheme(window.matchMedia('(prefers-color-scheme: dark)').matches)
|
|
||||||
updateThemeButtons()
|
|
||||||
})
|
|
||||||
|
|
||||||
window
|
|
||||||
.matchMedia('(prefers-color-scheme: dark)')
|
|
||||||
.addEventListener('change', (event) => {
|
|
||||||
if (localStorage.theme === 'system') {
|
|
||||||
toggleTheme(event.matches)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
document.addEventListener('scroll', onScroll)
|
document.addEventListener('scroll', onScroll)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateThemeButtons() {
|
|
||||||
const theme = localStorage.getItem('theme')
|
|
||||||
const lightThemeButton = document.getElementById('light-theme-button')
|
|
||||||
const darkThemeButton = document.getElementById('dark-theme-button')
|
|
||||||
const systemThemeButton = document.getElementById('system-theme-button')
|
|
||||||
|
|
||||||
function removeActiveButtonTheme(button) {
|
|
||||||
button?.classList.remove('bg-black/5')
|
|
||||||
button?.classList.remove('dark:bg-white/5')
|
|
||||||
}
|
|
||||||
|
|
||||||
function addActiveButtonTheme(button) {
|
|
||||||
button?.classList.add('bg-black/5')
|
|
||||||
button?.classList.add('dark:bg-white/5')
|
|
||||||
}
|
|
||||||
|
|
||||||
removeActiveButtonTheme(lightThemeButton)
|
|
||||||
removeActiveButtonTheme(darkThemeButton)
|
|
||||||
removeActiveButtonTheme(systemThemeButton)
|
|
||||||
|
|
||||||
if (theme === 'light') {
|
|
||||||
addActiveButtonTheme(lightThemeButton)
|
|
||||||
} else if (theme === 'dark') {
|
|
||||||
addActiveButtonTheme(darkThemeButton)
|
|
||||||
} else {
|
|
||||||
addActiveButtonTheme(systemThemeButton)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function animate() {
|
|
||||||
const animateElements = document.querySelectorAll('.animate')
|
|
||||||
|
|
||||||
animateElements.forEach((element, index) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
element.classList.add('show')
|
|
||||||
}, index * 100)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function onScroll() {
|
function onScroll() {
|
||||||
if (window.scrollY > 0) {
|
if (window.scrollY > 0) {
|
||||||
document.documentElement.classList.add('scrolled')
|
document.documentElement.classList.add('scrolled')
|
||||||
|
@ -151,44 +67,6 @@ const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleTheme(dark) {
|
|
||||||
const css = document.createElement('style')
|
|
||||||
|
|
||||||
css.appendChild(
|
|
||||||
document.createTextNode(
|
|
||||||
`* {
|
|
||||||
-webkit-transition: none !important;
|
|
||||||
-moz-transition: none !important;
|
|
||||||
-o-transition: none !important;
|
|
||||||
-ms-transition: none !important;
|
|
||||||
transition: none !important;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
document.head.appendChild(css)
|
|
||||||
|
|
||||||
if (dark) {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
|
|
||||||
window.getComputedStyle(css).opacity
|
|
||||||
document.head.removeChild(css)
|
|
||||||
}
|
|
||||||
|
|
||||||
function preloadTheme() {
|
|
||||||
const userTheme = localStorage.theme
|
|
||||||
|
|
||||||
if (userTheme === 'light' || userTheme === 'dark') {
|
|
||||||
toggleTheme(true) // set default to dark theme
|
|
||||||
} else {
|
|
||||||
toggleTheme(window.matchMedia('(prefers-color-scheme: dark)').matches)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addCopyCodeButtons() {
|
function addCopyCodeButtons() {
|
||||||
let copyButtonLabel = '📋'
|
let copyButtonLabel = '📋'
|
||||||
let codeBlocks = Array.from(document.querySelectorAll('pre'))
|
let codeBlocks = Array.from(document.querySelectorAll('pre'))
|
||||||
|
@ -228,5 +106,4 @@ const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => init())
|
document.addEventListener('DOMContentLoaded', () => init())
|
||||||
document.addEventListener('astro:after-swap', () => init())
|
document.addEventListener('astro:after-swap', () => init())
|
||||||
preloadTheme()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,33 +2,30 @@
|
||||||
import Container from '@components/Container.astro'
|
import Container from '@components/Container.astro'
|
||||||
import Link from '@components/Link.astro'
|
import Link from '@components/Link.astro'
|
||||||
import { SITE } from '@consts'
|
import { SITE } from '@consts'
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{ href: '/blog', label: 'blog' },
|
||||||
|
{ href: '/authors', label: 'authors' },
|
||||||
|
{ href: '/about', label: 'about' },
|
||||||
|
{ href: '/tags', label: 'tags' },
|
||||||
|
]
|
||||||
---
|
---
|
||||||
|
|
||||||
<header transition:persist>
|
<header class="sticky top-0 z-10" transition:persist>
|
||||||
<Container>
|
<Container>
|
||||||
<div class="flex flex-wrap justify-between gap-y-2">
|
<div class="flex items-center justify-between py-4">
|
||||||
<Link href="/" underline={false}>
|
<Link href="/" underline={false}>
|
||||||
<div class="font-semibold">
|
{SITE.TITLE}<span class="ml-1">🍄</span>
|
||||||
{SITE.TITLE} 🍄
|
|
||||||
</div>
|
|
||||||
</Link>
|
</Link>
|
||||||
<nav class="flex items-center gap-1 text-sm">
|
<nav class="flex items-center space-x-1 text-sm">
|
||||||
<Link href="/blog">blog</Link>
|
{
|
||||||
<span>
|
items.map((item, index) => (
|
||||||
{`/`}
|
<>
|
||||||
</span>
|
<Link href={item.href}>{item.label}</Link>
|
||||||
<Link href="/authors">authors</Link>
|
{index < items.length - 1 && <span class="text-gray-400">/</span>}
|
||||||
<span>
|
</>
|
||||||
{`/`}
|
))
|
||||||
</span>
|
}
|
||||||
<Link href="/about">about</Link>
|
|
||||||
<span>
|
|
||||||
{`/`}
|
|
||||||
</span>
|
|
||||||
<Link href="/tags">tags</Link>
|
|
||||||
<span>
|
|
||||||
{`/`}
|
|
||||||
</span>
|
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
---
|
---
|
||||||
import type { CollectionEntry } from "astro:content";
|
import type { CollectionEntry } from 'astro:content'
|
||||||
import { Image } from "astro:assets";
|
import { Image } from 'astro:assets'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
member: CollectionEntry<"authors">;
|
member: CollectionEntry<'authors'>
|
||||||
};
|
}
|
||||||
|
|
||||||
const { member } = Astro.props;
|
const { member } = Astro.props
|
||||||
const { name, avatar, bio } = member.data;
|
const { name, avatar, bio } = member.data
|
||||||
---
|
---
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="animate not-prose flex flex-col sm:flex-row size-full sm:items-center gap-4 overflow-hidden rounded-xl border border-foreground bg-background p-6 hover:bg-secondary"
|
class="not-prose flex size-full flex-col gap-4 overflow-hidden rounded-xl border border-foreground bg-background p-6 hover:bg-secondary sm:flex-row sm:items-center"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={avatar}
|
src={avatar}
|
||||||
|
|
|
@ -27,10 +27,7 @@ function buildToc(headings: Heading[]) {
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<details
|
<details open class="rounded-lg border border-black/15 dark:border-white/20">
|
||||||
open
|
|
||||||
class="animate rounded-lg border border-black/15 dark:border-white/20"
|
|
||||||
>
|
|
||||||
<summary>Table of Contents</summary>
|
<summary>Table of Contents</summary>
|
||||||
<nav class="">
|
<nav class="">
|
||||||
<ul class="py-3">
|
<ul class="py-3">
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: "enscribe"
|
name: 'enscribe'
|
||||||
avatar: "https://gravatar.com/avatar/9bfdc4ec972793cf05cb91efce5f4aaaec2a0da1bf4ec34dad0913f1d845faf6.webp?size=256"
|
avatar: 'https://gravatar.com/avatar/9bfdc4ec972793cf05cb91efce5f4aaaec2a0da1bf4ec34dad0913f1d845faf6.webp?size=256'
|
||||||
bio: "d(-_-)b"
|
bio: 'd(-_-)b'
|
||||||
website: "https://enscribe.dev"
|
website: 'https://enscribe.dev'
|
||||||
twitter: "enscry"
|
twitter: 'enscry'
|
||||||
github: "jktrn"
|
github: 'jktrn'
|
||||||
---
|
---
|
|
@ -62,7 +62,7 @@ When developing you can continue to use `npm run dev` and Pagefind will use the
|
||||||
|
|
||||||
## UI enhancements 🎨
|
## UI enhancements 🎨
|
||||||
|
|
||||||
- Elements are styled and animate on focus
|
- Elements are styled and on focus
|
||||||
- Increased contrast in light mode
|
- Increased contrast in light mode
|
||||||
- Active theme is indicated by theme buttons
|
- Active theme is indicated by theme buttons
|
||||||
- Separate syntax highlight themes for light and dark mode
|
- Separate syntax highlight themes for light and dark mode
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { defineCollection, reference, z } from "astro:content";
|
import { defineCollection, reference, z } from 'astro:content'
|
||||||
|
|
||||||
const blog = defineCollection({
|
const blog = defineCollection({
|
||||||
type: "content",
|
type: 'content',
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
|
@ -9,12 +9,12 @@ const blog = defineCollection({
|
||||||
draft: z.boolean().optional(),
|
draft: z.boolean().optional(),
|
||||||
|
|
||||||
tags: z.array(z.string()).optional(),
|
tags: z.array(z.string()).optional(),
|
||||||
author: z.union([reference("authors"), z.string()]).optional(),
|
author: z.union([reference('authors'), z.string()]).optional(),
|
||||||
}),
|
}),
|
||||||
});
|
})
|
||||||
|
|
||||||
const authors = defineCollection({
|
const authors = defineCollection({
|
||||||
type: "content",
|
type: 'content',
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
avatar: z.string().url(),
|
avatar: z.string().url(),
|
||||||
|
@ -26,6 +26,6 @@ const authors = defineCollection({
|
||||||
mail: z.string().email().optional(),
|
mail: z.string().email().optional(),
|
||||||
discord: z.string().optional(),
|
discord: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
});
|
})
|
||||||
|
|
||||||
export const collections = { blog, authors };
|
export const collections = { blog, authors }
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Header from '@components/Header.astro'
|
||||||
import Footer from '@components/Footer.astro'
|
import Footer from '@components/Footer.astro'
|
||||||
import { SITE } from '@consts'
|
import { SITE } from '@consts'
|
||||||
import '../styles/katex.css'
|
import '../styles/katex.css'
|
||||||
|
import { ViewTransitions } from 'astro:transitions'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string
|
title: string
|
||||||
|
@ -17,10 +18,13 @@ const { title, description } = Astro.props
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<Head title={`${title} | ${SITE.TITLE}`} description={description} />
|
<Head title={`${title} | ${SITE.TITLE}`} description={description} />
|
||||||
|
<ViewTransitions />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body
|
||||||
|
class="box-border flex h-fit min-h-screen flex-col px-4 font-sans antialiased"
|
||||||
|
>
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main class="flex-grow">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|
|
@ -9,10 +9,10 @@ import { SITE } from '@consts'
|
||||||
<Layout title="404" description={SITE.DESCRIPTION}>
|
<Layout title="404" description={SITE.DESCRIPTION}>
|
||||||
<Container>
|
<Container>
|
||||||
<div class="mt-16 grid place-items-center gap-3">
|
<div class="mt-16 grid place-items-center gap-3">
|
||||||
<h4 class="animate text-2xl font-semibold text-black dark:text-white">
|
<h4 class="text-2xl font-semibold text-black dark:text-white">
|
||||||
404: Page not found
|
404: Page not found
|
||||||
</h4>
|
</h4>
|
||||||
<span class="animate">
|
<span>
|
||||||
<BackToPrevious href="/">Go to home page</BackToPrevious>
|
<BackToPrevious href="/">Go to home page</BackToPrevious>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,8 +8,8 @@ import { Image } from 'astro:assets'
|
||||||
<Layout title="About" description="About">
|
<Layout title="About" description="About">
|
||||||
<Container>
|
<Container>
|
||||||
<div class="space-y-10">
|
<div class="space-y-10">
|
||||||
<div class="animate font-semibold text-black dark:text-white">About</div>
|
<div class="font-semibold text-black dark:text-white">About</div>
|
||||||
<section class="animate not-prose flex flex-col gap-4 text-justify">
|
<section class="not-prose flex flex-col gap-4 text-justify">
|
||||||
<p class="text-justify">
|
<p class="text-justify">
|
||||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores porro
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores porro
|
||||||
hic minima incidunt explicabo obcaecati consectetur consequuntur at
|
hic minima incidunt explicabo obcaecati consectetur consequuntur at
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
---
|
---
|
||||||
import { type CollectionEntry, getCollection, getEntry } from "astro:content";
|
import { type CollectionEntry, getCollection, getEntry } from 'astro:content'
|
||||||
import Layout from "@layouts/Layout.astro";
|
import Layout from '@layouts/Layout.astro'
|
||||||
import MemberCard from "@components/MemberCard.astro";
|
import MemberCard from '@components/MemberCard.astro'
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const authors = await getCollection("authors");
|
const authors = await getCollection('authors')
|
||||||
return authors.map((member) => ({
|
return authors.map((member) => ({
|
||||||
params: { slug: member.slug },
|
params: { slug: member.slug },
|
||||||
props: { member },
|
props: { member },
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
member: CollectionEntry<"authors">;
|
member: CollectionEntry<'authors'>
|
||||||
};
|
}
|
||||||
|
|
||||||
const { member } = Astro.props;
|
const { member } = Astro.props
|
||||||
|
|
||||||
const allPosts = await getCollection("blog");
|
const allPosts = await getCollection('blog')
|
||||||
const memberPosts = allPosts
|
const memberPosts = allPosts
|
||||||
.filter((post) => {
|
.filter((post) => {
|
||||||
if (typeof post.data.author === 'string') {
|
if (typeof post.data.author === 'string') {
|
||||||
return post.data.author === member.data.name && !post.data.draft;
|
return post.data.author === member.data.name && !post.data.draft
|
||||||
} else if (post.data.author && 'slug' in post.data.author) {
|
} else if (post.data.author && 'slug' in post.data.author) {
|
||||||
return post.data.author.slug === member.slug && !post.data.draft;
|
return post.data.author.slug === member.slug && !post.data.draft
|
||||||
}
|
}
|
||||||
return false;
|
return false
|
||||||
})
|
})
|
||||||
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
|
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf())
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout
|
<Layout
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
---
|
---
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from 'astro:content'
|
||||||
import Layout from "@layouts/Layout.astro";
|
import Layout from '@layouts/Layout.astro'
|
||||||
import MemberCard from "@components/MemberCard.astro";
|
import MemberCard from '@components/MemberCard.astro'
|
||||||
|
|
||||||
const authors = await getCollection("authors");
|
const authors = await getCollection('authors')
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="authors" description="authors">
|
<Layout title="authors" description="authors">
|
||||||
<section>
|
<section>
|
||||||
<ul
|
<ul class="not-prose grid grid-cols-1 gap-4 lg:grid-cols-2 xl:grid-cols-3">
|
||||||
class="animate not-prose grid grid-cols-1 gap-4 lg:grid-cols-2 xl:grid-cols-3"
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
authors.map((member) => (
|
authors.map((member) => (
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -53,7 +53,7 @@ const { Content, headings } = await post.render()
|
||||||
<BackToPrevious href="/blog">Back to blog</BackToPrevious>
|
<BackToPrevious href="/blog">Back to blog</BackToPrevious>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-10 space-y-4">
|
<div class="my-10 space-y-4">
|
||||||
<div class="animate flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5">
|
||||||
<div class="font-base text-sm">
|
<div class="font-base text-sm">
|
||||||
<FormattedDate date={post.data.date} />
|
<FormattedDate date={post.data.date} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -62,7 +62,7 @@ const { Content, headings } = await post.render()
|
||||||
{readingTime(post.body)}
|
{readingTime(post.body)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="animate text-4xl font-semibold text-black dark:text-white">
|
<h1 class="text-4xl font-semibold text-black dark:text-white">
|
||||||
{post.data.title}
|
{post.data.title}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="font-base text-sm">
|
<div class="font-base text-sm">
|
||||||
|
|
|
@ -30,7 +30,7 @@ const years = Object.keys(posts).sort((a, b) => parseInt(b) - parseInt(a))
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
{
|
{
|
||||||
years.map((year) => (
|
years.map((year) => (
|
||||||
<section class="animate space-y-4">
|
<section class="space-y-4">
|
||||||
<div class="font-semibold text-black dark:text-white">{year}</div>
|
<div class="font-semibold text-black dark:text-white">{year}</div>
|
||||||
<div>
|
<div>
|
||||||
<ul class="not-prose flex flex-col gap-4">
|
<ul class="not-prose flex flex-col gap-4">
|
||||||
|
|
|
@ -16,7 +16,7 @@ const blog = (await getCollection('blog'))
|
||||||
|
|
||||||
<Layout title="Home" description="Home">
|
<Layout title="Home" description="Home">
|
||||||
<Container>
|
<Container>
|
||||||
<section class="animate space-y-6">
|
<section class="space-y-6">
|
||||||
<div class="flex flex-wrap items-center justify-between gap-y-2">
|
<div class="flex flex-wrap items-center justify-between gap-y-2">
|
||||||
<h2 class="font-semibold text-black dark:text-white">Latest posts</h2>
|
<h2 class="font-semibold text-black dark:text-white">Latest posts</h2>
|
||||||
<Link href="/blog"> See all posts </Link>
|
<Link href="/blog"> See all posts </Link>
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
import rss from '@astrojs/rss'
|
import rss from '@astrojs/rss'
|
||||||
import { SITE } from '@consts'
|
import { SITE } from '@consts'
|
||||||
import { getCollection } from 'astro:content'
|
|
||||||
import type { APIContext } from 'astro'
|
import type { APIContext } from 'astro'
|
||||||
|
import { getCollection } from 'astro:content'
|
||||||
|
|
||||||
export async function GET(context: APIContext) {
|
export async function GET(context: APIContext) {
|
||||||
try {
|
try {
|
||||||
const blog = (await getCollection('blog')).filter(
|
const blog = (await getCollection('blog')).filter(
|
||||||
(post) => !post.data.draft
|
(post) => !post.data.draft,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filter posts by tag 'rss-feed'
|
// Filter posts by tag 'rss-feed'
|
||||||
const filteredBlogs = blog.filter(
|
const filteredBlogs = blog.filter(
|
||||||
(post) => post.data.tags && post.data.tags.includes('rss-feed')
|
(post) => post.data.tags && post.data.tags.includes('rss-feed'),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sort posts by date
|
// Sort posts by date
|
||||||
const items = [...filteredBlogs].sort(
|
const items = [...filteredBlogs].sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
new Date(b.data.date).valueOf() - new Date(a.data.date).valueOf()
|
new Date(b.data.date).valueOf() - new Date(a.data.date).valueOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Return RSS feed
|
// Return RSS feed
|
||||||
|
|
|
@ -36,7 +36,7 @@ export async function getStaticPaths() {
|
||||||
>
|
>
|
||||||
<Container>
|
<Container>
|
||||||
<div class="space-y-10">
|
<div class="space-y-10">
|
||||||
<div class="animate font-semibold text-black dark:text-white">
|
<div class="font-semibold text-black dark:text-white">
|
||||||
Tag: <span
|
Tag: <span
|
||||||
class="mx-2 rounded-full bg-orange-300 px-3 py-2 transition-colors duration-300 ease-in-out hover:bg-cyan-200 dark:bg-orange-500 dark:hover:bg-cyan-500"
|
class="mx-2 rounded-full bg-orange-300 px-3 py-2 transition-colors duration-300 ease-in-out hover:bg-cyan-200 dark:bg-orange-500 dark:hover:bg-cyan-500"
|
||||||
>#{tag}</span
|
>#{tag}</span
|
||||||
|
@ -45,7 +45,7 @@ export async function getStaticPaths() {
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
{
|
{
|
||||||
posts.map((post) => (
|
posts.map((post) => (
|
||||||
<section class="animate space-y-4">
|
<section class="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<ul class="not-prose flex flex-col gap-4">
|
<ul class="not-prose flex flex-col gap-4">
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -14,7 +14,7 @@ const tags = blog
|
||||||
<Layout title="Tags" description="Tags">
|
<Layout title="Tags" description="Tags">
|
||||||
<Container>
|
<Container>
|
||||||
<div class="space-y-10">
|
<div class="space-y-10">
|
||||||
<div class="animate font-semibold text-black dark:text-white">Tags</div>
|
<div class="font-semibold text-black dark:text-white">Tags</div>
|
||||||
<ul class="flex flex-wrap">
|
<ul class="flex flex-wrap">
|
||||||
{
|
{
|
||||||
tags.map((tag) => (
|
tags.map((tag) => (
|
||||||
|
|
|
@ -2,42 +2,6 @@
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
html {
|
|
||||||
overflow-y: auto;
|
|
||||||
color-scheme: light;
|
|
||||||
scroll-padding-top: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.dark {
|
|
||||||
color-scheme: dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
@apply size-full;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
@apply font-sans antialiased;
|
|
||||||
@apply flex flex-col;
|
|
||||||
@apply bg-neutral-300 dark:bg-slate-900;
|
|
||||||
@apply text-black/75 dark:text-white/75;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
@apply fixed left-0 right-0 top-0 z-50 py-6;
|
|
||||||
@apply bg-neutral-100/75 dark:bg-neutral-900/75;
|
|
||||||
@apply saturate-200 backdrop-blur-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
@apply flex-1 py-32;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
@apply py-6 text-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
article {
|
article {
|
||||||
@apply prose prose-neutral max-w-full dark:prose-invert prose-img:mx-auto prose-img:my-auto;
|
@apply prose prose-neutral max-w-full dark:prose-invert prose-img:mx-auto prose-img:my-auto;
|
||||||
@apply prose-headings:font-semibold;
|
@apply prose-headings:font-semibold;
|
||||||
|
@ -61,15 +25,6 @@ article {
|
||||||
scrollbar-color: #1e293b #0f172a;
|
scrollbar-color: #1e293b #0f172a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.animate {
|
|
||||||
@apply -translate-y-3 opacity-0;
|
|
||||||
@apply transition-all duration-300 ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate.show {
|
|
||||||
@apply translate-y-0 opacity-100;
|
|
||||||
}
|
|
||||||
|
|
||||||
html #back-to-top {
|
html #back-to-top {
|
||||||
@apply pointer-events-none opacity-0;
|
@apply pointer-events-none opacity-0;
|
||||||
}
|
}
|
||||||
|
@ -123,3 +78,65 @@ pre {
|
||||||
.copy-code:active {
|
.copy-code:active {
|
||||||
@apply scale-90 transition-transform;
|
@apply scale-90 transition-transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 0 0% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 0 0% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 0 0% 3.9%;
|
||||||
|
--primary: 0 0% 9%;
|
||||||
|
--primary-foreground: 0 0% 98%;
|
||||||
|
--secondary: 0 0% 96.1%;
|
||||||
|
--secondary-foreground: 0 0% 9%;
|
||||||
|
--muted: 0 0% 96.1%;
|
||||||
|
--muted-foreground: 0 0% 45.1%;
|
||||||
|
--accent: 0 0% 96.1%;
|
||||||
|
--accent-foreground: 0 0% 9%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 0 0% 89.8%;
|
||||||
|
--input: 0 0% 89.8%;
|
||||||
|
--ring: 0 0% 3.9%;
|
||||||
|
--chart-1: 12 76% 61%;
|
||||||
|
--chart-2: 173 58% 39%;
|
||||||
|
--chart-3: 197 37% 24%;
|
||||||
|
--chart-4: 43 74% 66%;
|
||||||
|
--chart-5: 27 87% 67%;
|
||||||
|
--radius: 0.5rem;
|
||||||
|
}
|
||||||
|
.dark {
|
||||||
|
--background: 0 0% 3.9%;
|
||||||
|
--foreground: 0 0% 98%;
|
||||||
|
--card: 0 0% 3.9%;
|
||||||
|
--card-foreground: 0 0% 98%;
|
||||||
|
--popover: 0 0% 3.9%;
|
||||||
|
--popover-foreground: 0 0% 98%;
|
||||||
|
--primary: 0 0% 98%;
|
||||||
|
--primary-foreground: 0 0% 9%;
|
||||||
|
--secondary: 0 0% 14.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 0 0% 14.9%;
|
||||||
|
--muted-foreground: 0 0% 63.9%;
|
||||||
|
--accent: 0 0% 14.9%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 0 0% 14.9%;
|
||||||
|
--input: 0 0% 14.9%;
|
||||||
|
--ring: 0 0% 83.1%;
|
||||||
|
--chart-1: 220 70% 50%;
|
||||||
|
--chart-2: 160 60% 45%;
|
||||||
|
--chart-3: 30 80% 55%;
|
||||||
|
--chart-4: 280 65% 60%;
|
||||||
|
--chart-5: 340 75% 55%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type { Config } from 'tailwindcss'
|
||||||
import defaultTheme from 'tailwindcss/defaultTheme'
|
import defaultTheme from 'tailwindcss/defaultTheme'
|
||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
darkMode: 'class',
|
darkMode: ['class', 'class'],
|
||||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
|
@ -10,9 +10,56 @@ const config: Config = {
|
||||||
sans: ['Geist Sans', ...defaultTheme.fontFamily.sans],
|
sans: ['Geist Sans', ...defaultTheme.fontFamily.sans],
|
||||||
mono: ['Geist Mono', ...defaultTheme.fontFamily.mono],
|
mono: ['Geist Mono', ...defaultTheme.fontFamily.mono],
|
||||||
},
|
},
|
||||||
|
borderRadius: {
|
||||||
|
lg: 'var(--radius)',
|
||||||
|
md: 'calc(var(--radius) - 2px)',
|
||||||
|
sm: 'calc(var(--radius) - 4px)',
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
background: 'hsl(var(--background))',
|
||||||
|
foreground: 'hsl(var(--foreground))',
|
||||||
|
card: {
|
||||||
|
DEFAULT: 'hsl(var(--card))',
|
||||||
|
foreground: 'hsl(var(--card-foreground))',
|
||||||
|
},
|
||||||
|
popover: {
|
||||||
|
DEFAULT: 'hsl(var(--popover))',
|
||||||
|
foreground: 'hsl(var(--popover-foreground))',
|
||||||
|
},
|
||||||
|
primary: {
|
||||||
|
DEFAULT: 'hsl(var(--primary))',
|
||||||
|
foreground: 'hsl(var(--primary-foreground))',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: 'hsl(var(--secondary))',
|
||||||
|
foreground: 'hsl(var(--secondary-foreground))',
|
||||||
|
},
|
||||||
|
muted: {
|
||||||
|
DEFAULT: 'hsl(var(--muted))',
|
||||||
|
foreground: 'hsl(var(--muted-foreground))',
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: 'hsl(var(--accent))',
|
||||||
|
foreground: 'hsl(var(--accent-foreground))',
|
||||||
|
},
|
||||||
|
destructive: {
|
||||||
|
DEFAULT: 'hsl(var(--destructive))',
|
||||||
|
foreground: 'hsl(var(--destructive-foreground))',
|
||||||
|
},
|
||||||
|
border: 'hsl(var(--border))',
|
||||||
|
input: 'hsl(var(--input))',
|
||||||
|
ring: 'hsl(var(--ring))',
|
||||||
|
chart: {
|
||||||
|
'1': 'hsl(var(--chart-1))',
|
||||||
|
'2': 'hsl(var(--chart-2))',
|
||||||
|
'3': 'hsl(var(--chart-3))',
|
||||||
|
'4': 'hsl(var(--chart-4))',
|
||||||
|
'5': 'hsl(var(--chart-5))',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [require('@tailwindcss/typography')],
|
},
|
||||||
|
},
|
||||||
|
plugins: [require('@tailwindcss/typography'), require('tailwindcss-animate')],
|
||||||
}
|
}
|
||||||
|
|
||||||
export default config
|
export default config
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@*": ["./src/*"]
|
"@*": ["./src/*"]
|
||||||
}
|
},
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"jsxImportSource": "react"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue