diff --git a/package.json b/package.json index a26d875..8bf188e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "astroplate", - "version": "5.7.0", + "version": "5.8.0", "description": "Astro and Tailwindcss boilerplate", "author": "zeon.studio", "license": "MIT", @@ -17,12 +17,12 @@ }, "dependencies": { "@astrojs/check": "0.9.5", - "@astrojs/mdx": "4.3.8", - "@astrojs/react": "4.4.0", + "@astrojs/mdx": "4.3.9", + "@astrojs/react": "4.4.1", "@astrojs/sitemap": "3.6.0", "@digi4care/astro-google-tagmanager": "^1.6.0", - "@justinribeiro/lite-youtube": "^1.8.2", - "astro": "5.15.1", + "@justinribeiro/lite-youtube": "^1.9.0", + "astro": "5.15.3", "astro-auto-import": "^0.4.5", "astro-font": "^1.1.0", "date-fns": "^4.1.0", @@ -43,10 +43,10 @@ "@tailwindcss/forms": "^0.5.10", "@tailwindcss/typography": "^0.5.19", "@tailwindcss/vite": "^4.1.16", - "@types/node": "24.9.1", + "@types/node": "24.10.0", "@types/react": "19.2.2", "@types/react-dom": "19.2.2", - "eslint": "^9.38.0", + "eslint": "^9.39.1", "prettier": "^3.6.2", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-tailwindcss": "^0.7.1", diff --git a/readme.md b/readme.md index 15ad7fa..6b8aad4 100755 --- a/readme.md +++ b/readme.md @@ -10,8 +10,8 @@

- - Astro Version 5.14 + + Astro Version 5.15 @@ -67,7 +67,7 @@ ### 📦 Dependencies -- astro v5.7+ +- astro v5.15+ - node v20.10+ - yarn v1.22+ - tailwind v4+ diff --git a/src/config/config.json b/src/config/config.json index d2250a6..fac4e6a 100755 --- a/src/config/config.json +++ b/src/config/config.json @@ -22,6 +22,12 @@ "blog_folder": "blog" }, + "announcement": { + "enable": true, + "content": "♥️ Loving Astroplate? Please ⭐️ on Github", + "expire_days": 7 + }, + "params": { "contact_form_action": "#", "copyright": "Designed And Developed by [Zeon Studio](https://zeon.studio)" diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro index efa4634..f67b47e 100755 --- a/src/layouts/Base.astro +++ b/src/layouts/Base.astro @@ -12,6 +12,7 @@ import { } from "@digi4care/astro-google-tagmanager"; import { AstroFont } from "astro-font"; import { ClientRouter } from "astro:transitions"; +import Announcement from "./helpers/Announcement"; import SearchModal from "./helpers/SearchModal"; // font families @@ -189,6 +190,7 @@ const { title, meta_title, description, image, noindex, canonical } = } +

diff --git a/src/layouts/helpers/Announcement.tsx b/src/layouts/helpers/Announcement.tsx new file mode 100644 index 0000000..11e78c3 --- /dev/null +++ b/src/layouts/helpers/Announcement.tsx @@ -0,0 +1,88 @@ +import config from "@/config/config.json"; +import { markdownify } from "@/lib/utils/textConverter"; +import React, { useEffect, useState } from "react"; + +const { enable, content, expire_days } = config.announcement; + +const Cookies = { + set: (name: string, value: string, options: any = {}) => { + if (typeof document === "undefined") return; + + const defaults = { path: "/" }; + const opts = { ...defaults, ...options }; + + if (typeof opts.expires === "number") { + opts.expires = new Date(Date.now() + opts.expires * 864e5); + } + if (opts.expires instanceof Date) { + opts.expires = opts.expires.toUTCString(); + } + + let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`; + + for (let key in opts) { + if (!opts[key]) continue; + cookieString += `; ${key}`; + if (opts[key] !== true) { + cookieString += `=${opts[key]}`; + } + } + + document.cookie = cookieString; + }, + + get: (name: string): string | null => { + if (typeof document === "undefined") return null; + + const cookies = document.cookie.split("; "); + for (let cookie of cookies) { + const [key, value] = cookie.split("="); + if (decodeURIComponent(key) === name) { + return decodeURIComponent(value); + } + } + return null; + }, + + remove: (name: string, options: any = {}) => { + Cookies.set(name, "", { ...options, expires: -1 }); + }, +}; + +const Announcement: React.FC = () => { + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + if (enable && content && !Cookies.get("announcement-close")) { + setIsVisible(true); + } + }, []); + + const handleClose = () => { + Cookies.set("announcement-close", "true", { + expires: expire_days, + }); + setIsVisible(false); + }; + + if (!enable || !content || !isVisible) { + return null; + } + + return ( +
+

+ +

+ ); +}; + +export default Announcement;