diff --git a/astro.config.mjs b/astro.config.mjs index 47fb2f9..11e45b2 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -27,7 +27,8 @@ export default defineConfig({ icon({ include: { 'material-symbols': ['*'], - 'fa6-brands': ['*'] + 'fa6-brands': ['*'], + 'fa6-regular': ['*'] } }) ], diff --git a/package.json b/package.json index fae23fb..2cb1150 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "devDependencies": { "@astrojs/ts-plugin": "^1.1.3", "@iconify-json/fa6-brands": "^1.1.13", + "@iconify-json/fa6-regular": "^1.1.13", "@iconify-json/material-symbols": "^1.1.59", "@rollup/plugin-yaml": "^4.1.2", "@tailwindcss/typography": "^0.5.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 062eeba..aa1832c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -58,6 +58,9 @@ devDependencies: '@iconify-json/fa6-brands': specifier: ^1.1.13 version: 1.1.13 + '@iconify-json/fa6-regular': + specifier: ^1.1.13 + version: 1.1.13 '@iconify-json/material-symbols': specifier: ^1.1.59 version: 1.1.59 @@ -981,6 +984,12 @@ packages: '@iconify/types': 2.0.0 dev: true + /@iconify-json/fa6-regular@1.1.13: + resolution: {integrity: sha512-wY5nEeWwg+fdDzfPdzOHcbgiN7Qk2bTyO0BreJUQJb8NKPcXivyHAlkWPc+wA0kQwfqrmekVCwWnrLoD7B9T0g==} + dependencies: + '@iconify/types': 2.0.0 + dev: true + /@iconify-json/material-symbols@1.1.59: resolution: {integrity: sha512-azzJVyS2AKQ4cxIUUmeMHaTVlU9aWM6M98NEqf8luZ1RJpVWuDdSjExY+x58Y39wPFTf+6hgvS4pRwCJRdpohw==} dependencies: diff --git a/src/components/GlobalStyles.astro b/src/components/GlobalStyles.astro index d62ab27..a135aa2 100644 --- a/src/components/GlobalStyles.astro +++ b/src/components/GlobalStyles.astro @@ -88,6 +88,8 @@ color_set({ --codeblock-selection: oklch(0.40 0.08 var(--hue)) --codeblock-bg: oklch(0.2 0.015 var(--hue)) oklch(0.17 0.015 var(--hue)) + --license-block-bg: black(0.03) var(--codeblock-bg) + --link-hover: oklch(0.95 0.025 var(--hue)) oklch(0.40 0.08 var(--hue)) --link-active: oklch(0.90 0.05 var(--hue)) oklch(0.35 0.07 var(--hue)) diff --git a/src/components/misc/License.astro b/src/components/misc/License.astro new file mode 100644 index 0000000..f5b93ef --- /dev/null +++ b/src/components/misc/License.astro @@ -0,0 +1,47 @@ +--- +import {formatDateToYYYYMMDD} from "../../utils/date-utils"; +interface Props { + title: string; + slug: string; + pubDate: Date; + class: string; +} + +const { title, slug, pubDate } = Astro.props; +const className = Astro.props.class; + +import { Icon } from 'astro-icon/components'; +import {licenseConfig, profileConfig} from "../../config"; +import {getFullUrl, getPostUrlBySlug} from "../../utils/url-utils"; +import {i18n} from "../../i18n/translation"; +import I18nKey from "../../i18n/i18nKey"; + +const profileConf = profileConfig; +const licenseConf = licenseConfig; + +const postUrl = getFullUrl(getPostUrlBySlug(slug)); + +--- +
+
+ {title} +
+ + {postUrl} + +
+
+
{i18n(I18nKey.author)}
+
{profileConf.name}
+
+
+
{i18n(I18nKey.publishedAt)}
+
{formatDateToYYYYMMDD(pubDate)}
+
+
+
{i18n(I18nKey.license)}
+ {licenseConf.name} +
+
+ +
\ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 04134a3..43b6d96 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,10 +1,11 @@ -import type {NavBarConfig, ProfileConfig, SiteConfig} from "./types/config.ts"; +import type {LicenseConfig, NavBarConfig, ProfileConfig, SiteConfig} from "./types/config.ts"; import {LinkPreset} from "./types/config.ts"; export const siteConfig: SiteConfig = { title: 'Fuwari', subtitle: 'Demo Site', - lang: 'en-US', + url: 'https://fuwari.vercel.app/', + lang: 'en', themeHue: 250, banner: { enable: true, @@ -44,4 +45,10 @@ export const profileConfig: ProfileConfig = { url: 'https://github.com/saicaca/fuwari', } ] +} + +export const licenseConfig: LicenseConfig = { + enable: true, + name: 'CC BY-NC-SA 4.0', + url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/', } \ No newline at end of file diff --git a/src/i18n/i18nKey.ts b/src/i18n/i18nKey.ts index 991c219..5dd4b60 100644 --- a/src/i18n/i18nKey.ts +++ b/src/i18n/i18nKey.ts @@ -23,6 +23,10 @@ enum I18nKey { primaryColor = "primaryColor", more = "more", + + author = "author", + publishedAt = "publishedAt", + license = "license", } export default I18nKey; \ No newline at end of file diff --git a/src/i18n/languages/en.ts b/src/i18n/languages/en.ts index c45f0b4..3061f59 100644 --- a/src/i18n/languages/en.ts +++ b/src/i18n/languages/en.ts @@ -26,4 +26,8 @@ export const en: Translation = { [Key.primaryColor]: "Primary Color", [Key.more]: "More", + + [Key.author]: "Author", + [Key.publishedAt]: "Published at", + [Key.license]: "License", }; diff --git a/src/i18n/languages/zh_CN.ts b/src/i18n/languages/zh_CN.ts index 583111c..3d534dd 100644 --- a/src/i18n/languages/zh_CN.ts +++ b/src/i18n/languages/zh_CN.ts @@ -26,4 +26,8 @@ export const zh_CN: Translation = { [Key.primaryColor]: "主题色", [Key.more]: "更多", + + [Key.author]: "作者", + [Key.publishedAt]: "发布于", + [Key.license]: "许可协议", }; \ No newline at end of file diff --git a/src/i18n/languages/zh_TW.ts b/src/i18n/languages/zh_TW.ts index 4e9510b..a16c614 100644 --- a/src/i18n/languages/zh_TW.ts +++ b/src/i18n/languages/zh_TW.ts @@ -26,4 +26,8 @@ export const zh_TW: Translation = { [Key.primaryColor]: "主題色", [Key.more]: "更多", + + [Key.author]: "作者", + [Key.publishedAt]: "發佈於", + [Key.license]: "許可協議", }; diff --git a/src/pages/posts/[slug].astro b/src/pages/posts/[slug].astro index a91197e..61bd6a9 100644 --- a/src/pages/posts/[slug].astro +++ b/src/pages/posts/[slug].astro @@ -8,7 +8,8 @@ import Button from "../../components/control/Button.astro"; import {i18n} from "../../i18n/translation"; import I18nKey from "../../i18n/i18nKey"; import {getPostUrlBySlug} from "../../utils/url-utils"; -import CommentLayout from "../../components/comment/CommentLayout.astro"; +import License from "../../components/misc/License.astro"; +import {licenseConfig} from "../../config"; export async function getStaticPaths() { const blogEntries = await getCollection('posts'); @@ -25,7 +26,7 @@ const { remarkPluginFrontmatter } = await entry.render(); ---
-
@@ -73,13 +74,15 @@ const { remarkPluginFrontmatter } = await entry.render(); {!entry.data.image &&
} -
+ {licenseConfig.enable && } +
@@ -183,7 +186,7 @@ const { remarkPluginFrontmatter } = await entry.render(); &:after content: none img - border-radius: 8px + border-radius: 12px hr border-color: var(--line-divider) border-style: dashed diff --git a/src/types/config.ts b/src/types/config.ts index 96c3061..18a2844 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,6 +1,7 @@ export type SiteConfig = { title: string, subtitle: string, + url: string, lang: string, @@ -36,4 +37,10 @@ export type ProfileConfig = { url: string, icon: string, }[], -}; \ No newline at end of file +}; + +export type LicenseConfig = { + enable: boolean; + name: string, + url: string, +} \ No newline at end of file diff --git a/src/utils/url-utils.ts b/src/utils/url-utils.ts index fdbbe3f..0404a93 100644 --- a/src/utils/url-utils.ts +++ b/src/utils/url-utils.ts @@ -1,9 +1,16 @@ +import {siteConfig} from "../config.ts"; + export function pathsEqual(path1: string, path2: string) { const normalizedPath1 = path1.replace(/^\/|\/$/g, '').toLowerCase(); const normalizedPath2 = path2.replace(/^\/|\/$/g, '').toLowerCase(); return normalizedPath1 === normalizedPath2; } +function joinUrl(...parts: string[]): string { + const joined = parts.join('/'); + return joined.replace(/([^:]\/)\/+/g, '$1'); +} + export function getPostUrlBySlug(slug: string): string | null { if (!slug) return null; @@ -16,3 +23,6 @@ export function getCategoryUrl(category: string): string | null { return `/archive/category/${category}`; } +export function getFullUrl(path: string): string { + return joinUrl(siteConfig.url, path); +} \ No newline at end of file