Copyright © {currentYear}
|
diff --git a/src/components/ShareLinks.astro b/src/components/ShareLinks.astro
deleted file mode 100644
index d65a0de1ea..0000000000
--- a/src/components/ShareLinks.astro
+++ /dev/null
@@ -1,26 +0,0 @@
----
-import { SHARE_LINKS } from "@/constants";
-import LinkButton from "./LinkButton.astro";
-
-const URL = Astro.url;
----
-
-{
- SHARE_LINKS.length > 0 && (
-
-
Share this post on:
-
- {SHARE_LINKS.map(social => (
-
-
- {social.linkTitle}
-
- ))}
-
-
- )
-}
diff --git a/src/components/Socials.astro b/src/components/Socials.astro
deleted file mode 100644
index 545fca7b5d..0000000000
--- a/src/components/Socials.astro
+++ /dev/null
@@ -1,25 +0,0 @@
----
-import { SOCIALS } from "@/constants";
-import LinkButton from "./LinkButton.astro";
-
-export interface Props {
- centered?: boolean;
-}
-
-const { centered = false } = Astro.props;
----
-
-
- {
- SOCIALS.map(social => (
-
-
- {social.linkTitle}
-
- ))
- }
-
diff --git a/src/components/constants/ShareLinks.astro b/src/components/constants/ShareLinks.astro
new file mode 100644
index 0000000000..bd9bb370bd
--- /dev/null
+++ b/src/components/constants/ShareLinks.astro
@@ -0,0 +1,31 @@
+---
+import LinkButton from "@/components/LinkButton.astro";
+import { getCollection } from "astro:content";
+import { getSocialIcons } from "./utils";
+
+const shareLinkCollection = await getCollection("shareLinks");
+
+const shareLinks = await getSocialIcons(shareLinkCollection);
+
+const URL = Astro.url;
+---
+
+{
+ shareLinks.length > 0 && (
+
+
Share this post on:
+
+ {shareLinks.map(shareLink => (
+
+
+ {shareLink.linkTitle}
+
+ ))}
+
+
+ )
+}
diff --git a/src/components/constants/SocialLinks.astro b/src/components/constants/SocialLinks.astro
new file mode 100644
index 0000000000..cda85bb413
--- /dev/null
+++ b/src/components/constants/SocialLinks.astro
@@ -0,0 +1,37 @@
+---
+import { getCollection } from "astro:content";
+import LinkButton from "@/components/LinkButton.astro";
+import { getSocialIcons } from "./utils";
+import SocialLinksContainer from "./SocialLinksContainer.astro";
+
+const socialsCollection = await getCollection("socials");
+const socials = await getSocialIcons(socialsCollection);
+
+export interface Props {
+ minimal?: boolean;
+ size?: number;
+}
+
+const { minimal = false, size = 26 } = Astro.props;
+---
+
+{
+ socials.length > 0 && (
+
+ {socials.map(social => (
+
+
+ {social.linkTitle}
+
+ ))}
+
+ )
+}
diff --git a/src/components/constants/SocialLinksContainer.astro b/src/components/constants/SocialLinksContainer.astro
new file mode 100644
index 0000000000..de026229a6
--- /dev/null
+++ b/src/components/constants/SocialLinksContainer.astro
@@ -0,0 +1,24 @@
+---
+export interface Props {
+ minimal?: boolean;
+}
+
+const { minimal = false } = Astro.props;
+
+const containerClass = ["flex-wrap justify-center gap-1", { flex: minimal }];
+---
+
+{
+ minimal ? (
+
+
+
+ ) : (
+
+ )
+}
diff --git a/src/components/constants/_share.json b/src/components/constants/_share.json
new file mode 100644
index 0000000000..0c82d1e40d
--- /dev/null
+++ b/src/components/constants/_share.json
@@ -0,0 +1,38 @@
+[
+ {
+ "id": "whatsapp",
+ "name": "WhatsApp",
+ "href": "https://wa.me/?text=",
+ "linkTitle": "Share this post via WhatsApp"
+ },
+ {
+ "id": "facebook",
+ "name": "Facebook",
+ "href": "https://www.facebook.com/sharer.php?u=",
+ "linkTitle": "Share this post on Facebook"
+ },
+ {
+ "id": "x",
+ "name": "X",
+ "href": "https://x.com/intent/post?url=",
+ "linkTitle": "Share this post on X"
+ },
+ {
+ "id": "telegram",
+ "name": "Telegram",
+ "href": "https://t.me/share/url?url=",
+ "linkTitle": "Share this post via Telegram"
+ },
+ {
+ "id": "pinterest",
+ "name": "Pinterest",
+ "href": "https://pinterest.com/pin/create/button/?url=",
+ "linkTitle": "Share this post on Pinterest"
+ },
+ {
+ "id": "mail",
+ "name": "Mail",
+ "href": "mailto:?subject=See%20this%20post&body=",
+ "linkTitle": "Share this post via email"
+ }
+]
diff --git a/src/components/constants/_social.json b/src/components/constants/_social.json
new file mode 100644
index 0000000000..4eb2ec8815
--- /dev/null
+++ b/src/components/constants/_social.json
@@ -0,0 +1,26 @@
+[
+ {
+ "id": "github",
+ "name": "GitHub",
+ "href": "https://github.com/satnaing/astro-paper",
+ "linkTitle": "{title} on GitHub"
+ },
+ {
+ "id": "x",
+ "name": "X",
+ "href": "https://x.com/username",
+ "linkTitle": "{title} on X"
+ },
+ {
+ "id": "linkedin",
+ "name": "LinkedIn",
+ "href": "https://www.linkedin.com/in/username/",
+ "linkTitle": "{title} on LinkedIn"
+ },
+ {
+ "id": "mail",
+ "name": "Mail",
+ "href": "mailto:yourmail@gmail.com",
+ "linkTitle": "Send an email to {title}"
+ }
+]
diff --git a/src/assets/icons/IconFacebook.svg b/src/components/constants/icons/facebook.svg
similarity index 100%
rename from src/assets/icons/IconFacebook.svg
rename to src/components/constants/icons/facebook.svg
diff --git a/src/assets/icons/IconGitHub.svg b/src/components/constants/icons/github.svg
similarity index 100%
rename from src/assets/icons/IconGitHub.svg
rename to src/components/constants/icons/github.svg
diff --git a/src/assets/icons/IconLinkedin.svg b/src/components/constants/icons/linkedin.svg
similarity index 100%
rename from src/assets/icons/IconLinkedin.svg
rename to src/components/constants/icons/linkedin.svg
diff --git a/src/assets/icons/IconMail.svg b/src/components/constants/icons/mail.svg
similarity index 100%
rename from src/assets/icons/IconMail.svg
rename to src/components/constants/icons/mail.svg
diff --git a/src/assets/icons/IconPinterest.svg b/src/components/constants/icons/pinterest.svg
similarity index 100%
rename from src/assets/icons/IconPinterest.svg
rename to src/components/constants/icons/pinterest.svg
diff --git a/src/assets/icons/IconTelegram.svg b/src/components/constants/icons/telegram.svg
similarity index 100%
rename from src/assets/icons/IconTelegram.svg
rename to src/components/constants/icons/telegram.svg
diff --git a/src/assets/icons/IconWhatsapp.svg b/src/components/constants/icons/whatsapp.svg
similarity index 100%
rename from src/assets/icons/IconWhatsapp.svg
rename to src/components/constants/icons/whatsapp.svg
diff --git a/src/assets/icons/IconBrandX.svg b/src/components/constants/icons/x.svg
similarity index 100%
rename from src/assets/icons/IconBrandX.svg
rename to src/components/constants/icons/x.svg
diff --git a/src/components/constants/utils.ts b/src/components/constants/utils.ts
new file mode 100644
index 0000000000..b1b7a49037
--- /dev/null
+++ b/src/components/constants/utils.ts
@@ -0,0 +1,52 @@
+import type { Props } from "astro";
+import type { InferEntrySchema, RenderedContent } from "astro:content";
+import { SITE } from "@/config";
+
+export interface Social {
+ name: string;
+ href: string;
+ linkTitle: string;
+ icon: (_props: Props) => Element;
+}
+
+type CollectionKey = "socials" | "shareLinks";
+
+interface CollectionEntry {
+ id: string;
+ body?: string;
+ collection: CollectionKey;
+ data: InferEntrySchema
;
+ rendered?: RenderedContent;
+ filePath?: string;
+}
+
+export async function getSocialIcons(
+ list: CollectionEntry[]
+): Promise {
+ const socials: Social[] = [];
+
+ for (const { id, data } of list) {
+ // Import the icon dynamically based on the social id
+ const icon = await import(`./icons/${id}.svg`).catch(() => {
+ if (import.meta.env.DEV) {
+ throw new Error(
+ `[Socials]: Icon "${id}" not found. Please ensure the icon exists in the src/components/constants/icons directory.`
+ );
+ }
+ return null;
+ });
+
+ // Skip if icon import failed
+ if (!icon) {
+ continue;
+ }
+
+ socials.push({
+ ...data,
+ icon: icon.default,
+ linkTitle: data.linkTitle.replace("{title}", SITE.title),
+ });
+ }
+
+ return socials;
+}
diff --git a/src/constants.ts b/src/constants.ts
index a9004cdc31..65a16847f7 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,83 +1,3 @@
-import type { Props } from "astro";
-import IconMail from "@/assets/icons/IconMail.svg";
-import IconGitHub from "@/assets/icons/IconGitHub.svg";
-import IconBrandX from "@/assets/icons/IconBrandX.svg";
-import IconLinkedin from "@/assets/icons/IconLinkedin.svg";
-import IconWhatsapp from "@/assets/icons/IconWhatsapp.svg";
-import IconFacebook from "@/assets/icons/IconFacebook.svg";
-import IconTelegram from "@/assets/icons/IconTelegram.svg";
-import IconPinterest from "@/assets/icons/IconPinterest.svg";
-import { SITE } from "@/config";
-
-interface Social {
- name: string;
- href: string;
- linkTitle: string;
- icon: (_props: Props) => Element;
-}
-
-export const SOCIALS: Social[] = [
- {
- name: "GitHub",
- href: "https://github.com/satnaing/astro-paper",
- linkTitle: `${SITE.title} on GitHub`,
- icon: IconGitHub,
- },
- {
- name: "X",
- href: "https://x.com/username",
- linkTitle: `${SITE.title} on X`,
- icon: IconBrandX,
- },
- {
- name: "LinkedIn",
- href: "https://www.linkedin.com/in/username/",
- linkTitle: `${SITE.title} on LinkedIn`,
- icon: IconLinkedin,
- },
- {
- name: "Mail",
- href: "mailto:yourmail@gmail.com",
- linkTitle: `Send an email to ${SITE.title}`,
- icon: IconMail,
- },
-] as const;
-
-export const SHARE_LINKS: Social[] = [
- {
- name: "WhatsApp",
- href: "https://wa.me/?text=",
- linkTitle: `Share this post via WhatsApp`,
- icon: IconWhatsapp,
- },
- {
- name: "Facebook",
- href: "https://www.facebook.com/sharer.php?u=",
- linkTitle: `Share this post on Facebook`,
- icon: IconFacebook,
- },
- {
- name: "X",
- href: "https://x.com/intent/post?url=",
- linkTitle: `Share this post on X`,
- icon: IconBrandX,
- },
- {
- name: "Telegram",
- href: "https://t.me/share/url?url=",
- linkTitle: `Share this post via Telegram`,
- icon: IconTelegram,
- },
- {
- name: "Pinterest",
- href: "https://pinterest.com/pin/create/button/?url=",
- linkTitle: `Share this post on Pinterest`,
- icon: IconPinterest,
- },
- {
- name: "Mail",
- href: "mailto:?subject=See%20this%20post&body=",
- linkTitle: `Share this post via email`,
- icon: IconMail,
- },
-] as const;
+export const BLOG_PATH = "src/data/blog";
+export const SHARE_LINKS_PATH = "src/components/constants/_share.json";
+export const SOCIALS_PATH = "src/components/constants/_social.json";
diff --git a/src/content.config.ts b/src/content.config.ts
index 6119aa62a8..310718515d 100644
--- a/src/content.config.ts
+++ b/src/content.config.ts
@@ -1,8 +1,7 @@
import { defineCollection, z } from "astro:content";
-import { glob } from "astro/loaders";
+import { file, glob } from "astro/loaders";
import { SITE } from "@/config";
-
-export const BLOG_PATH = "src/data/blog";
+import { BLOG_PATH, SHARE_LINKS_PATH, SOCIALS_PATH } from "@/constants";
const blog = defineCollection({
loader: glob({ pattern: "**/[^_]*.md", base: `./${BLOG_PATH}` }),
@@ -23,4 +22,20 @@ const blog = defineCollection({
}),
});
-export const collections = { blog };
+const socialSchema = z.object({
+ name: z.string(),
+ href: z.string(),
+ linkTitle: z.string(),
+});
+
+const socials = defineCollection({
+ loader: file(`./${SOCIALS_PATH}`),
+ schema: socialSchema,
+});
+
+const shareLinks = defineCollection({
+ loader: file(`./${SHARE_LINKS_PATH}`),
+ schema: socialSchema,
+});
+
+export const collections = { blog, socials, shareLinks };
diff --git a/src/layouts/PostDetails.astro b/src/layouts/PostDetails.astro
index 23def5d28e..9a7036627b 100644
--- a/src/layouts/PostDetails.astro
+++ b/src/layouts/PostDetails.astro
@@ -6,7 +6,7 @@ import Footer from "@/components/Footer.astro";
import Tag from "@/components/Tag.astro";
import Datetime from "@/components/Datetime.astro";
import EditPost from "@/components/EditPost.astro";
-import ShareLinks from "@/components/ShareLinks.astro";
+import ShareLinks from "@/components/constants/ShareLinks.astro";
import BackButton from "@/components/BackButton.astro";
import BackToTopButton from "@/components/BackToTopButton.astro";
import { getPath } from "@/utils/getPath";
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 8f0ce93653..c776b6858c 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -3,15 +3,14 @@ import { getCollection } from "astro:content";
import Layout from "@/layouts/Layout.astro";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
-import Socials from "@/components/Socials.astro";
-import LinkButton from "@/components/LinkButton.astro";
-import Card from "@/components/Card.astro";
import Hr from "@/components/Hr.astro";
+import Card from "@/components/Card.astro";
+import LinkButton from "@/components/LinkButton.astro";
+import SocialsLinks from "@/components/constants/SocialLinks.astro";
import getSortedPosts from "@/utils/getSortedPosts";
import IconRss from "@/assets/icons/IconRss.svg";
import IconArrowRight from "@/assets/icons/IconArrowRight.svg";
import { SITE } from "@/config";
-import { SOCIALS } from "@/constants";
const posts = await getCollection("blog");
@@ -57,15 +56,7 @@ const recentPosts = sortedPosts.filter(({ data }) => !data.featured);
README
for more info.
- {
- // only display if at least one social link is enabled
- SOCIALS.length > 0 && (
-
- )
- }
+
diff --git a/src/utils/getPath.ts b/src/utils/getPath.ts
index 057b612fe1..5172597f48 100644
--- a/src/utils/getPath.ts
+++ b/src/utils/getPath.ts
@@ -1,4 +1,4 @@
-import { BLOG_PATH } from "@/content.config";
+import { BLOG_PATH } from "@/constants";
import { slugifyStr } from "./slugify";
/**