From e081c546247fba03caf1a1a949f63c4c2fc7c718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B3=E5=85=83=E7=9A=93?= Date: Thu, 8 May 2025 20:48:51 +0800 Subject: [PATCH] feat: update footer link formatting and add shadcn-nuxt integration - Refactored footer.vue to improve link formatting. - Updated nuxt.config.ts to include shadcn-nuxt and added necessary HTML attributes and meta tags for SEO. - Added new dependencies in package.json for class-variance-authority, clsx, lucide-vue-next, reka-ui, shadcn-nuxt, tailwind-merge, and tailwindcss-animate. - Cleaned up unused template tags in headlines.vue, index.vue, and news/[provider]/[slug].vue. - Simplified sources.vue template structure. - Improved login.vue styles for better animation. - Enhanced google.ts API handler for better error handling and code clarity. - Updated find/newsOrg.ts to ensure consistent code style. - Added CSS variables and improved Tailwind configuration in main.css and tailwind.config.js. - Created components.json for shadcn integration and added new UI components (Alert, Button, Progress) with respective styles and variants. - Implemented utility functions in utils.ts for class name merging and value updating. --- README.md | 6 +- bun.lock | 59 +++++++++++++++- components.json | 20 ++++++ components/footer.vue | 4 +- components/ui/alert/Alert.vue | 16 +++++ components/ui/alert/AlertDescription.vue | 14 ++++ components/ui/alert/AlertTitle.vue | 14 ++++ components/ui/alert/index.ts | 23 +++++++ components/ui/button/Button.vue | 26 +++++++ components/ui/button/index.ts | 36 ++++++++++ components/ui/progress/Progress.vue | 39 +++++++++++ components/ui/progress/index.ts | 1 + lib/utils.ts | 18 +++++ nuxt.config.ts | 60 +++++++++++++++++ package.json | 7 ++ pages/app/headlines.vue | 4 +- pages/app/hot/index.vue | 86 +++++++++++++++--------- pages/app/index.vue | 4 +- pages/app/news/[provider]/[slug].vue | 4 +- pages/sources.vue | 5 +- pages/system/login.vue | 14 ++-- server/api/rss/google.ts | 39 +++++------ server/routes/find/newsOrg.ts | 6 +- styles/main.css | 26 +++++++ tailwind.config.js | 50 +++++++++++++- 25 files changed, 502 insertions(+), 79 deletions(-) create mode 100644 components.json create mode 100644 components/ui/alert/Alert.vue create mode 100644 components/ui/alert/AlertDescription.vue create mode 100644 components/ui/alert/AlertTitle.vue create mode 100644 components/ui/alert/index.ts create mode 100644 components/ui/button/Button.vue create mode 100644 components/ui/button/index.ts create mode 100644 components/ui/progress/Progress.vue create mode 100644 components/ui/progress/index.ts create mode 100644 lib/utils.ts diff --git a/README.md b/README.md index 0676e22..a5ea031 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # 新聞解析 / News Analyze ## Why? + 我們使用這個新聞來舉例: + ``` 朱立倫批政府像希特勒德國在台協會:不應為政治扭曲歷史| 政治 - 中央社 CNA 5/7/2025, 11:17:00 PM @@ -12,9 +14,11 @@ - 「朱立倫道歉」!亂比喻遭德國、以色列譴責 民進黨:賠上台灣國際名譽 - 奇摩新聞 - 洪聖斐觀點》獨裁餘毒罵人「法西斯」 朱立倫東施效顰共產黨| 政治 - Newtalk新聞 ``` + 你會看到許多觀點,但不知道這些新聞為什麼會寫比較偏見的文章。 ## Stack: + - Postgres - Passport.js - Tailwind @@ -25,4 +29,4 @@ - Minio S3 - Nuxt i18N - BunJS -- Groq \ No newline at end of file +- Groq diff --git a/bun.lock b/bun.lock index edf68a3..01c3f4b 100644 --- a/bun.lock +++ b/bun.lock @@ -17,13 +17,20 @@ "@uploadthing/nuxt": "^7.1.7", "animate.css": "^4.1.1", "bootstrap-icons": "^1.12.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "gsap": "^3.13.0", "html-to-json-parser": "^2.0.1", + "lucide-vue-next": "^0.508.0", "nuxt": "^3.17.2", "passport-github2": "^0.1.12", "prettier": "^3.5.3", + "reka-ui": "^2.2.1", "rss-parser": "^3.13.0", + "shadcn-nuxt": "2.1.0", + "tailwind-merge": "^3.2.0", "tailwindcss": "3", + "tailwindcss-animate": "^1.0.7", "tailwindcss-animatecss": "^3.0.5", "uploadthing": "^7.6.0", "vue": "^3.5.13", @@ -182,6 +189,14 @@ "@fastify/busboy": ["@fastify/busboy@3.1.1", "", {}, "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw=="], + "@floating-ui/core": ["@floating-ui/core@1.7.0", "", { "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.7.0", "", { "dependencies": { "@floating-ui/core": "^1.7.0", "@floating-ui/utils": "^0.2.9" } }, "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="], + + "@floating-ui/vue": ["@floating-ui/vue@1.1.6", "", { "dependencies": { "@floating-ui/dom": "^1.0.0", "@floating-ui/utils": "^0.2.9", "vue-demi": ">=0.13.0" } }, "sha512-XFlUzGHGv12zbgHNk5FN2mUB7ROul3oG2ENdTpWdE+qMFxyNxWSRmsoyhiEnpmabNm6WnUvR1OvJfUfN4ojC1A=="], + "@fontsource-variable/noto-sans-tc": ["@fontsource-variable/noto-sans-tc@5.2.5", "", {}, "sha512-oaAn5hkLxraNBOWuiqyJ6+t1SmQ9Sszmcs+wJpmAmUO/1dsaHjDU5HXEjutvPpucqVeqdvVNr/kHRx+ghdiPeA=="], "@fontsource/fira-code": ["@fontsource/fira-code@5.2.6", "", {}, "sha512-wCkIpPm0BqlkCPLYeY4Vui96ODmVUV0/GpEe3OfJ4v8EJn/BF2SlyxvarFsTs1CKiGjrO2cXlIZbBrKi9F+hUQ=="], @@ -198,6 +213,10 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.2", "", {}, "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ=="], + "@internationalized/date": ["@internationalized/date@3.8.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-J51AJ0fEL68hE4CwGPa6E0PO6JDaVLd8aln48xFCSy7CZkZc96dGEGmLs2OEEbBxcsVZtfrqkXJwI2/MSG8yKw=="], + + "@internationalized/number": ["@internationalized/number@3.6.1", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-UVsb4bCwbL944E0SX50CHFtWEeZ2uB5VozZ5yDXJdq6iPZsZO5p+bjVMZh2GxHf4Bs/7xtDCcPwEa2NU9DaG/g=="], + "@intlify/bundle-utils": ["@intlify/bundle-utils@10.0.1", "", { "dependencies": { "@intlify/message-compiler": "^11.1.2", "@intlify/shared": "^11.1.2", "acorn": "^8.8.2", "escodegen": "^2.1.0", "estree-walker": "^2.0.2", "jsonc-eslint-parser": "^2.3.0", "mlly": "^1.2.0", "source-map-js": "^1.0.1", "yaml-eslint-parser": "^1.2.2" } }, "sha512-WkaXfSevtpgtUR4t8K2M6lbR7g03mtOxFeh+vXp5KExvPqS12ppaRj1QxzwRuRI5VUto54A22BjKoBMLyHILWQ=="], "@intlify/core": ["@intlify/core@10.0.7", "", { "dependencies": { "@intlify/core-base": "10.0.7", "@intlify/shared": "10.0.7" } }, "sha512-4n9tKt0/HcPrXfm0ceQlNC/wsgrrfXyHwRHSSiekMAy5vkOBc4PJXB5aUHGGkkH0dDdlkYyxUWqhZ3V64+gcKw=="], @@ -462,6 +481,8 @@ "@standard-schema/spec": ["@standard-schema/spec@1.0.0-beta.4", "", {}, "sha512-d3IxtzLo7P1oZ8s8YNvxzBUXRXojSut8pbPrTYtzsc5sn4+53jVqbk66pQerSZbZSJZQux6LkclB/+8IDordHg=="], + "@swc/helpers": ["@swc/helpers@0.5.17", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A=="], + "@tailwindcss/node": ["@tailwindcss/node@4.1.5", "", { "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.29.2", "tailwindcss": "4.1.5" } }, "sha512-CBhSWo0vLnWhXIvpD0qsPephiaUYfHUX3U9anwDaHZAeuGpTiB3XmsxPAN6qX7bFhipyGBqOa1QYQVVhkOUGxg=="], "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.5", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.5", "@tailwindcss/oxide-darwin-arm64": "4.1.5", "@tailwindcss/oxide-darwin-x64": "4.1.5", "@tailwindcss/oxide-freebsd-x64": "4.1.5", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.5", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.5", "@tailwindcss/oxide-linux-arm64-musl": "4.1.5", "@tailwindcss/oxide-linux-x64-gnu": "4.1.5", "@tailwindcss/oxide-linux-x64-musl": "4.1.5", "@tailwindcss/oxide-wasm32-wasi": "4.1.5", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.5", "@tailwindcss/oxide-win32-x64-msvc": "4.1.5" } }, "sha512-1n4br1znquEvyW/QuqMKQZlBen+jxAbvyduU87RS8R3tUSvByAkcaMTkJepNIrTlYhD+U25K4iiCIxE6BGdRYA=="], @@ -492,6 +513,10 @@ "@tailwindcss/vite": ["@tailwindcss/vite@4.1.5", "", { "dependencies": { "@tailwindcss/node": "4.1.5", "@tailwindcss/oxide": "4.1.5", "tailwindcss": "4.1.5" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-FE1stRoqdHSb7RxesMfCXE8icwI1W6zGE/512ae3ZDrpkQYTTYeSyUJPRCjZd8CwVAhpDUbi1YR8pcZioFJQ/w=="], + "@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.8", "", {}, "sha512-BT6w89Hqy7YKaWewYzmecXQzcJh6HTBbKYJIIkMaNU49DZ06LoTV3z32DWWEdUsgW6n1xTmwTLs4GtWrZC261w=="], + + "@tanstack/vue-virtual": ["@tanstack/vue-virtual@3.13.8", "", { "dependencies": { "@tanstack/virtual-core": "3.13.8" }, "peerDependencies": { "vue": "^2.7.0 || ^3.0.0" } }, "sha512-CqyjKVc88YlE8JPth8a5Gi4CUoYrwJ2PZxtFbhoekx8Z2qqymxX2jzkbUMKFsX4EVNET90D5bLsG3epyozbzcg=="], + "@trysound/sax": ["@trysound/sax@0.2.0", "", {}, "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="], @@ -586,11 +611,11 @@ "@vue/shared": ["@vue/shared@3.5.13", "", {}, "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="], - "@vueuse/core": ["@vueuse/core@13.1.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "13.1.0", "@vueuse/shared": "13.1.0" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q=="], + "@vueuse/core": ["@vueuse/core@12.8.2", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" } }, "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ=="], - "@vueuse/metadata": ["@vueuse/metadata@13.1.0", "", {}, "sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw=="], + "@vueuse/metadata": ["@vueuse/metadata@12.8.2", "", {}, "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A=="], - "@vueuse/shared": ["@vueuse/shared@13.1.0", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-IVS/qRRjhPTZ6C2/AM3jieqXACGwFZwWTdw5sNTSKk2m/ZpkuuN+ri+WCVUP8TqaKwJYt/KuMwmXspMAw8E6ew=="], + "@vueuse/shared": ["@vueuse/shared@12.8.2", "", { "dependencies": { "vue": "^3.5.13" } }, "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w=="], "@whatwg-node/disposablestack": ["@whatwg-node/disposablestack@0.0.6", "", { "dependencies": { "@whatwg-node/promise-helpers": "^1.0.0", "tslib": "^2.6.3" } }, "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw=="], @@ -644,6 +669,8 @@ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "aria-hidden": ["aria-hidden@1.2.4", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A=="], + "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], "ast-kit": ["ast-kit@1.4.3", "", { "dependencies": { "@babel/parser": "^7.27.0", "pathe": "^2.0.3" } }, "sha512-MdJqjpodkS5J149zN0Po+HPshkTdUyrvF7CKTafUgv69vBSPtncrj+3IiUgqdd7ElIEkbeXCsEouBUwLrw9Ilg=="], @@ -742,10 +769,14 @@ "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + "clipboardy": ["clipboardy@4.0.0", "", { "dependencies": { "execa": "^8.0.1", "is-wsl": "^3.1.0", "is64bit": "^2.0.0" } }, "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w=="], "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="], "co": ["co@4.6.0", "", {}, "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ=="], @@ -1378,6 +1409,8 @@ "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "lucide-vue-next": ["lucide-vue-next@0.508.0", "", { "peerDependencies": { "vue": ">=3.0.1" } }, "sha512-ZPO/Kh1gz7RU2/hd8FWw3SjLVMUIm/TJAhOGV9CbM1zvNwiJ8DK6W33LFWxtlZZ1IUPOXAny0pbttY+yyOsjKg=="], + "luxon": ["luxon@3.6.1", "", {}, "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ=="], "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], @@ -1754,6 +1787,8 @@ "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="], + "reka-ui": ["reka-ui@2.2.1", "", { "dependencies": { "@floating-ui/dom": "^1.6.13", "@floating-ui/vue": "^1.1.6", "@internationalized/date": "^3.5.0", "@internationalized/number": "^3.5.0", "@tanstack/vue-virtual": "^3.12.0", "@vueuse/core": "^12.5.0", "@vueuse/shared": "^12.5.0", "aria-hidden": "^1.2.4", "defu": "^6.1.4", "ohash": "^2.0.11" }, "peerDependencies": { "vue": ">= 3.2.0" } }, "sha512-oLHiyBn6gTIQGnTnv8G5LQuFp9j8HuUNl0qdnW3XPhFb/07hrxzFpjo2kt/jxOZive+n/XWDbOjSj2h9Hih3qA=="], + "remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="], "replace-in-file": ["replace-in-file@6.3.5", "", { "dependencies": { "chalk": "^4.1.2", "glob": "^7.2.0", "yargs": "^17.2.1" }, "bin": { "replace-in-file": "bin/cli.js" } }, "sha512-arB9d3ENdKva2fxRnSjwBEXfK1npgyci7ZZuwysgAp7ORjHSyxz6oqIjTEv8R0Ydl4Ll7uOAZXL4vbkhGIizCg=="], @@ -1816,6 +1851,8 @@ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + "shadcn-nuxt": ["shadcn-nuxt@2.1.0", "", { "dependencies": { "@nuxt/kit": "^3.15.4", "@oxc-parser/wasm": "^0.50.0", "typescript": "5.6.3" } }, "sha512-Pm9gYOgyReVaj2SeBAvHCo6lcJ2J+bUFWOlCfa3ml8xJd54uHtige4wdG0kJifutabCIKPu6Y+Ik+l94VR3GXQ=="], + "sharp": ["sharp@0.32.6", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.2", "node-addon-api": "^6.1.0", "prebuild-install": "^7.1.1", "semver": "^7.5.4", "simple-get": "^4.0.1", "tar-fs": "^3.0.4", "tunnel-agent": "^0.6.0" } }, "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], @@ -1916,8 +1953,12 @@ "tailwind-config-viewer": ["tailwind-config-viewer@2.0.4", "", { "dependencies": { "@koa/router": "^12.0.1", "commander": "^6.0.0", "fs-extra": "^9.0.1", "koa": "^2.14.2", "koa-static": "^5.0.0", "open": "^7.0.4", "portfinder": "^1.0.26", "replace-in-file": "^6.1.0" }, "peerDependencies": { "tailwindcss": "1 || 2 || 2.0.1-compat || 3" }, "bin": { "tailwind-config-viewer": "cli/index.js", "tailwindcss-config-viewer": "cli/index.js" } }, "sha512-icvcmdMmt9dphvas8wL40qttrHwAnW3QEN4ExJ2zICjwRsPj7gowd1cOceaWG3IfTuM/cTNGQcx+bsjMtmV+cw=="], + "tailwind-merge": ["tailwind-merge@3.2.0", "", {}, "sha512-FQT/OVqCD+7edmmJpsgCsY820RTD5AkBryuG5IUqR5YQZSdj5xlH5nLgH7YPths7WsLPSpSBNneJdM8aS8aeFA=="], + "tailwindcss": ["tailwindcss@3.4.17", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.6", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og=="], + "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], + "tailwindcss-animatecss": ["tailwindcss-animatecss@3.0.5", "", { "peerDependencies": { "tailwindcss": ">=3.1.0" } }, "sha512-5RDYryJ+O+xQfK1FhSPl1nIe4PPa1ZfHev21CpBGUNSRwUoLEoA6Oe2ftcuCWZEAa55jniqktbtkoHIoKS4jzQ=="], "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], @@ -2380,6 +2421,8 @@ "nuxt/oxc-parser": ["oxc-parser@0.68.1", "", { "dependencies": { "@oxc-project/types": "^0.68.1" }, "optionalDependencies": { "@oxc-parser/binding-darwin-arm64": "0.68.1", "@oxc-parser/binding-darwin-x64": "0.68.1", "@oxc-parser/binding-linux-arm-gnueabihf": "0.68.1", "@oxc-parser/binding-linux-arm64-gnu": "0.68.1", "@oxc-parser/binding-linux-arm64-musl": "0.68.1", "@oxc-parser/binding-linux-x64-gnu": "0.68.1", "@oxc-parser/binding-linux-x64-musl": "0.68.1", "@oxc-parser/binding-wasm32-wasi": "0.68.1", "@oxc-parser/binding-win32-arm64-msvc": "0.68.1", "@oxc-parser/binding-win32-x64-msvc": "0.68.1" } }, "sha512-dHwz+xP9r1GTvqyywfws4j7EEP/OaeTpHEjTcvIjViB/R2IdUn52AnoUFNjpw8yRU52XVE76rOA4IEj7I0EjnA=="], + "nuxt-link-checker/@vueuse/core": ["@vueuse/core@13.1.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "13.1.0", "@vueuse/shared": "13.1.0" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q=="], + "nypm/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], "open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], @@ -2416,6 +2459,10 @@ "router/path-to-regexp": ["path-to-regexp@8.2.0", "", {}, "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ=="], + "shadcn-nuxt/@oxc-parser/wasm": ["@oxc-parser/wasm@0.50.0", "", { "dependencies": { "@oxc-project/types": "^0.50.0" } }, "sha512-be/QsKqtXQbKhnIRzezPrV385L6EVaX1GNAGeaQaT+HX6Lny/SfmFetCrEZCRqn2/cAqo+P5rGDNJzv06dY/vw=="], + + "shadcn-nuxt/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], + "sharp/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], "sharp/node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="], @@ -2662,6 +2709,10 @@ "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + "nuxt-link-checker/@vueuse/core/@vueuse/metadata": ["@vueuse/metadata@13.1.0", "", {}, "sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw=="], + + "nuxt-link-checker/@vueuse/core/@vueuse/shared": ["@vueuse/shared@13.1.0", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-IVS/qRRjhPTZ6C2/AM3jieqXACGwFZwWTdw5sNTSKk2m/ZpkuuN+ri+WCVUP8TqaKwJYt/KuMwmXspMAw8E6ew=="], + "nuxt/oxc-parser/@oxc-parser/binding-darwin-arm64": ["@oxc-parser/binding-darwin-arm64@0.68.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y5FBQyPCLsldAZYEd+oZcUboXwpcLf42Lakx3EYtiYDbuK9M3IqBXMGxdM07P4PfGQrKYn6/cC8xAqkVHnbWPw=="], "nuxt/oxc-parser/@oxc-parser/binding-darwin-x64": ["@oxc-parser/binding-darwin-x64@0.68.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-nkiXpEKl8UOhNPdOY5hA2PFq9vQc9xVs7NFu2vUD9eH/j5uYfv8GnNaKkd+v6iH93JwEBxuK5gfwxiiCEMZRyg=="], @@ -2702,6 +2753,8 @@ "rollup-plugin-visualizer/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + "shadcn-nuxt/@oxc-parser/wasm/@oxc-project/types": ["@oxc-project/types@0.50.0", "", {}, "sha512-VGV87PmDCGv1D+57iEmIuDoso3ig8d8D4VIK9AS0H7h2aNiRwFoCpVyp01+3jvIuHjPcEM2wbo3NG5EKyfx6Jw=="], + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], diff --git a/components.json b/components.json new file mode 100644 index 0000000..c34b95f --- /dev/null +++ b/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://shadcn-vue.com/schema.json", + "style": "new-york", + "typescript": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "styles/main.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "composables": "@/composables", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib" + }, + "iconLibrary": "lucide" +} diff --git a/components/footer.vue b/components/footer.vue index 3878d0f..04d3ec6 100644 --- a/components/footer.vue +++ b/components/footer.vue @@ -12,9 +12,7 @@ const localeLink = useLocalePath(); Inspired by Ground.News - - Sources - + Sources diff --git a/components/ui/alert/Alert.vue b/components/ui/alert/Alert.vue new file mode 100644 index 0000000..c77836a --- /dev/null +++ b/components/ui/alert/Alert.vue @@ -0,0 +1,16 @@ + + + diff --git a/components/ui/alert/AlertDescription.vue b/components/ui/alert/AlertDescription.vue new file mode 100644 index 0000000..eca50ef --- /dev/null +++ b/components/ui/alert/AlertDescription.vue @@ -0,0 +1,14 @@ + + + diff --git a/components/ui/alert/AlertTitle.vue b/components/ui/alert/AlertTitle.vue new file mode 100644 index 0000000..e9c96ae --- /dev/null +++ b/components/ui/alert/AlertTitle.vue @@ -0,0 +1,14 @@ + + + diff --git a/components/ui/alert/index.ts b/components/ui/alert/index.ts new file mode 100644 index 0000000..2f09d98 --- /dev/null +++ b/components/ui/alert/index.ts @@ -0,0 +1,23 @@ +import { cva, type VariantProps } from "class-variance-authority"; + +export { default as Alert } from "./Alert.vue"; +export { default as AlertDescription } from "./AlertDescription.vue"; +export { default as AlertTitle } from "./AlertTitle.vue"; + +export const alertVariants = cva( + "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +export type AlertVariants = VariantProps; diff --git a/components/ui/button/Button.vue b/components/ui/button/Button.vue new file mode 100644 index 0000000..6c4c133 --- /dev/null +++ b/components/ui/button/Button.vue @@ -0,0 +1,26 @@ + + + diff --git a/components/ui/button/index.ts b/components/ui/button/index.ts new file mode 100644 index 0000000..de02b26 --- /dev/null +++ b/components/ui/button/index.ts @@ -0,0 +1,36 @@ +import { cva, type VariantProps } from "class-variance-authority"; + +export { default as Button } from "./Button.vue"; + +export const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2 rounded", + xs: "h-7 rounded px-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +export type ButtonVariants = VariantProps; diff --git a/components/ui/progress/Progress.vue b/components/ui/progress/Progress.vue new file mode 100644 index 0000000..1dfc1db --- /dev/null +++ b/components/ui/progress/Progress.vue @@ -0,0 +1,39 @@ + + + diff --git a/components/ui/progress/index.ts b/components/ui/progress/index.ts new file mode 100644 index 0000000..e934a9b --- /dev/null +++ b/components/ui/progress/index.ts @@ -0,0 +1 @@ +export { default as Progress } from "./Progress.vue"; diff --git a/lib/utils.ts b/lib/utils.ts new file mode 100644 index 0000000..3ec2403 --- /dev/null +++ b/lib/utils.ts @@ -0,0 +1,18 @@ +import type { Updater } from "@tanstack/vue-table"; +import type { Ref } from "vue"; +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +export function valueUpdater>( + updaterOrValue: T, + ref: Ref, +) { + ref.value = + typeof updaterOrValue === "function" + ? updaterOrValue(ref.value) + : updaterOrValue; +} diff --git a/nuxt.config.ts b/nuxt.config.ts index b7230fb..6f7b93d 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -13,6 +13,7 @@ export default defineNuxtConfig({ "@nuxtjs/seo", "@nuxtjs/i18n", "@nuxtjs/tailwindcss", + "shadcn-nuxt", ], i18n: { defaultLocale: "en", @@ -30,15 +31,63 @@ export default defineNuxtConfig({ app: { head: { title: "", + htmlAttrs: { + lang: "zh-Hant", + }, + link: [ + { rel: "dns-prefetch", href: "https://utfs.io" }, + { rel: "dns-prefetch", href: "https://s3.yhw.tw" }, + ], meta: [ { "http-equiv": "X-UA-Compatible", content: "IE=edge" }, { charset: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }, + + { + name: "keywords", + content: + "News Platform, Mini Wikipedia, News Comparison platform, 新聞平台, 米你維基百科, 新聞觀點比對平台", + }, + { + name: "og:keywords", + content: + "News Platform, Mini Wikipedia, News Comparison platform, 新聞平台, 米你維基百科, 新聞觀點比對平台", + }, + + { name: "author", content: "@hpware on GitHub" }, { name: "og:author", content: "@hpware on GitHub" }, + + { + name: "author:email", + content: "public+newscompareauthor@yuanhau.com", + }, { name: "og:author:email", content: "public+newscompareauthor@yuanhau.com", }, + + { name: "type", content: "website" }, + { name: "og:type", content: "website" }, + + { name: "locale", content: "zh_TW" }, + { name: "og:locale", content: "zh_TW" }, + + { name: "twitter:card", content: "summary_large_image" }, + { name: "copyright", content: "yh" }, + ], + script: [ + { + src: "https://data.yuanhau.com/script.js", + "data-website-id": "19c3756c-c9ac-489d-b9f0-0bb62579ed82", + defer: true, + }, + ], + noscript: [ + { + innerHTML: + "Sorry, but this website requires Javascript to function correctly.", + tagPriority: "critical", + }, ], }, }, @@ -48,4 +97,15 @@ export default defineNuxtConfig({ autoprefixer: {}, }, // Add your content paths here }, + shadcn: { + /** + * Prefix for all the imported component + */ + prefix: "", + /** + * Directory that the component lives in. + * @default "./components/ui" + */ + componentDir: "./components/ui", + }, }); diff --git a/package.json b/package.json index 7865676..d65dca6 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,20 @@ "@uploadthing/nuxt": "^7.1.7", "animate.css": "^4.1.1", "bootstrap-icons": "^1.12.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "gsap": "^3.13.0", "html-to-json-parser": "^2.0.1", + "lucide-vue-next": "^0.508.0", "nuxt": "^3.17.2", "passport-github2": "^0.1.12", "prettier": "^3.5.3", + "reka-ui": "^2.2.1", "rss-parser": "^3.13.0", + "shadcn-nuxt": "2.1.0", + "tailwind-merge": "^3.2.0", "tailwindcss": "3", + "tailwindcss-animate": "^1.0.7", "tailwindcss-animatecss": "^3.0.5", "uploadthing": "^7.6.0", "vue": "^3.5.13", diff --git a/pages/app/headlines.vue b/pages/app/headlines.vue index 27e0f69..cc340bc 100644 --- a/pages/app/headlines.vue +++ b/pages/app/headlines.vue @@ -1,3 +1 @@ - \ No newline at end of file + diff --git a/pages/app/hot/index.vue b/pages/app/hot/index.vue index d0f4b44..8b53289 100644 --- a/pages/app/hot/index.vue +++ b/pages/app/hot/index.vue @@ -1,38 +1,64 @@ \ No newline at end of file +
+ 類似新聞: +
+ +
+ + diff --git a/pages/app/index.vue b/pages/app/index.vue index 3797085..f55129b 100644 --- a/pages/app/index.vue +++ b/pages/app/index.vue @@ -1,3 +1,3 @@ \ No newline at end of file +

The "For you page"

+ diff --git a/pages/app/news/[provider]/[slug].vue b/pages/app/news/[provider]/[slug].vue index 5939319..c3995b0 100644 --- a/pages/app/news/[provider]/[slug].vue +++ b/pages/app/news/[provider]/[slug].vue @@ -4,6 +4,4 @@ const route = useRoute(); const provider = route.params.provider; const slug = route.params.slug; - \ No newline at end of file + diff --git a/pages/sources.vue b/pages/sources.vue index e525fc6..eb8e7f4 100644 --- a/pages/sources.vue +++ b/pages/sources.vue @@ -1,4 +1 @@ - \ No newline at end of file + diff --git a/pages/system/login.vue b/pages/system/login.vue index 50e0466..08b9e29 100644 --- a/pages/system/login.vue +++ b/pages/system/login.vue @@ -33,11 +33,11 @@ \ No newline at end of file + diff --git a/server/api/rss/google.ts b/server/api/rss/google.ts index 76ab1af..17d686f 100644 --- a/server/api/rss/google.ts +++ b/server/api/rss/google.ts @@ -1,29 +1,30 @@ -import Parser from 'rss-parser' -import { HTMLToJSON } from 'html-to-json-parser'; - +import Parser from "rss-parser"; +import { HTMLToJSON } from "html-to-json-parser"; export default defineEventHandler(async (event) => { let array = []; - const parser = new Parser() + const parser = new Parser(); try { - const feed = await parser.parseURL('https://news.google.com/rss?&hl=zh-TW&gl=TW&ceid=TW:zh-Hant') + const feed = await parser.parseURL( + "https://news.google.com/rss?&hl=zh-TW&gl=TW&ceid=TW:zh-Hant", + ); feed.items.forEach(async (item) => { - const rawRelatedNews = await HTMLToJSON(item.content, true) - const relatedNews = JSON.parse(rawRelatedNews.replace("ol", "")) - array.push({ - title: item.title, - link: item.link, - date: item.pubDate, - content: relatedNews - }); - console.log(item.title); - }) + const rawRelatedNews = await HTMLToJSON(item.content, true); + const relatedNews = JSON.parse(rawRelatedNews.replace("ol", "")); + array.push({ + title: item.title, + link: item.link, + date: item.pubDate, + content: relatedNews, + }); + console.log(item.title); + }); return array; } catch (error) { - console.error('Error fetching RSS:', error) + console.error("Error fetching RSS:", error); throw createError({ statusCode: 500, - message: 'Failed to fetch RSS feed' - }) + message: "Failed to fetch RSS feed", + }); } -}) \ No newline at end of file +}); diff --git a/server/routes/find/newsOrg.ts b/server/routes/find/newsOrg.ts index 704f9a6..21030a3 100644 --- a/server/routes/find/newsOrg.ts +++ b/server/routes/find/newsOrg.ts @@ -1,5 +1,5 @@ export default defineEventHandler(async (event) => { - const query = getQuery(event) - const name = query.name + const query = getQuery(event); + const name = query.name; return name; -}) \ No newline at end of file +}); diff --git a/styles/main.css b/styles/main.css index bf53037..bcf1953 100644 --- a/styles/main.css +++ b/styles/main.css @@ -13,6 +13,32 @@ body { font-family: "Noto Sans TC Variable", "Fira Sans", sans-serif; } + :root { + --background: bg-black; + --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%; + } } @font-face { diff --git a/tailwind.config.js b/tailwind.config.js index d9e0450..d959d3d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,14 +1,62 @@ /** @type {import('tailwindcss').Config} */ module.exports = { + darkMode: ["class"], content: [], theme: { extend: { backgroundColor: { page: "#000000", }, + 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: [], + plugins: [require("tailwindcss-animate")], corePlugins: { preflight: true, },