feat: add license block
This commit is contained in:
parent
a20c647495
commit
c642691dc8
|
@ -27,7 +27,8 @@ export default defineConfig({
|
|||
icon({
|
||||
include: {
|
||||
'material-symbols': ['*'],
|
||||
'fa6-brands': ['*']
|
||||
'fa6-brands': ['*'],
|
||||
'fa6-regular': ['*']
|
||||
}
|
||||
})
|
||||
],
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
---
|
||||
<div class=`relative transition overflow-hidden bg-[var(--license-block-bg)] py-5 px-6 ${className}`>
|
||||
<div class="transition font-bold text-black/75 dark:text-white/75">
|
||||
{title}
|
||||
</div>
|
||||
<a href={postUrl} class="link text-[var(--primary)]">
|
||||
{postUrl}
|
||||
</a>
|
||||
<div class="flex gap-6 mt-2">
|
||||
<div>
|
||||
<div class="transition text-black/30 dark:text-white/30 text-sm">{i18n(I18nKey.author)}</div>
|
||||
<div class="transition text-black/75 dark:text-white/75">{profileConf.name}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="transition text-black/30 dark:text-white/30 text-sm">{i18n(I18nKey.publishedAt)}</div>
|
||||
<div class="transition text-black/75 dark:text-white/75">{formatDateToYYYYMMDD(pubDate)}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="transition text-black/30 dark:text-white/30 text-sm">{i18n(I18nKey.license)}</div>
|
||||
<a href={licenseConf.url} target="_blank" class="link text-[var(--primary)]">{licenseConf.name}</a>
|
||||
</div>
|
||||
</div>
|
||||
<Icon name="fa6-brands:creative-commons" class="transition absolute right-6 top-1/2 -translate-y-1/2 text-black/5 dark:text-white/5" size="240"></Icon>
|
||||
</div>
|
|
@ -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,
|
||||
|
@ -45,3 +46,9 @@ export const profileConfig: ProfileConfig = {
|
|||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const licenseConfig: LicenseConfig = {
|
||||
enable: true,
|
||||
name: 'CC BY-NC-SA 4.0',
|
||||
url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/',
|
||||
}
|
|
@ -23,6 +23,10 @@ enum I18nKey {
|
|||
primaryColor = "primaryColor",
|
||||
|
||||
more = "more",
|
||||
|
||||
author = "author",
|
||||
publishedAt = "publishedAt",
|
||||
license = "license",
|
||||
}
|
||||
|
||||
export default I18nKey;
|
|
@ -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",
|
||||
};
|
||||
|
|
|
@ -26,4 +26,8 @@ export const zh_CN: Translation = {
|
|||
[Key.primaryColor]: "主题色",
|
||||
|
||||
[Key.more]: "更多",
|
||||
|
||||
[Key.author]: "作者",
|
||||
[Key.publishedAt]: "发布于",
|
||||
[Key.license]: "许可协议",
|
||||
};
|
|
@ -26,4 +26,8 @@ export const zh_TW: Translation = {
|
|||
[Key.primaryColor]: "主題色",
|
||||
|
||||
[Key.more]: "更多",
|
||||
|
||||
[Key.author]: "作者",
|
||||
[Key.publishedAt]: "發佈於",
|
||||
[Key.license]: "許可協議",
|
||||
};
|
||||
|
|
|
@ -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();
|
|||
---
|
||||
<MainGridLayout banner={entry.data.image} title={entry.data.title}>
|
||||
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative mb-4">
|
||||
<div class:list={["card-base z-10 px-4 md:px-9 pt-6 pb-10 relative w-full ",
|
||||
<div class:list={["card-base z-10 px-4 md:px-9 pt-6 pb-4 relative w-full ",
|
||||
{}
|
||||
]}>
|
||||
<!-- word count and reading time -->
|
||||
|
@ -73,13 +74,15 @@ const { remarkPluginFrontmatter } = await entry.render();
|
|||
|
||||
{!entry.data.image && <div class="border-[var(--line-divider)] border-dashed border-b-[1px] mb-5"></div>}
|
||||
|
||||
<div class="prose dark:prose-invert prose-sm md:prose-base max-w-none custom-md
|
||||
<div class="mb-6 prose dark:prose-invert prose-sm md:prose-base max-w-none custom-md
|
||||
">
|
||||
<!--<div class="prose dark:prose-invert max-w-none custom-md">-->
|
||||
<!--<div class="max-w-none custom-md">-->
|
||||
<Content />
|
||||
</div>
|
||||
|
||||
{licenseConfig.enable && <License title={entry.data.title} slug={entry.slug} pubDate={entry.data.published} class="mb-6 rounded-xl"></License>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export type SiteConfig = {
|
||||
title: string,
|
||||
subtitle: string,
|
||||
url: string,
|
||||
|
||||
lang: string,
|
||||
|
||||
|
@ -37,3 +38,9 @@ export type ProfileConfig = {
|
|||
icon: string,
|
||||
}[],
|
||||
};
|
||||
|
||||
export type LicenseConfig = {
|
||||
enable: boolean;
|
||||
name: string,
|
||||
url: string,
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue