Commit 541cdcb
Changed files (7)
packages
i18n
src
src
components
misc
widgets
packages/i18n/src/en/web/index.ts
@@ -52,6 +52,8 @@ const en_web = {
category: 'Category',
unTagged: 'No Tags',
unCategorized: 'Uncategorized',
+ wordsCount: 'Words Count',
+ readingTime: 'Reading Time',
},
info: {
toc: 'Table of Content',
packages/i18n/src/zh-CN/web/index.ts
@@ -52,6 +52,8 @@ const zh_CN_web = {
category: '分类',
unTagged: '无标签',
unCategorized: '未分类',
+ wordsCount: '字数统计',
+ readingTime: '阅读时间',
},
info: {
toc: '目录',
packages/i18n/src/zh-TW/web/index.ts
@@ -52,6 +52,8 @@ const zh_TW_web = {
category: '分類',
unTagged: '無標籤',
unCategorized: '未分類',
+ wordsCount: '字數統計',
+ readingTime: '閱讀時間',
},
info: {
toc: '目錄',
packages/i18n/src/i18n-types.ts
@@ -344,6 +344,14 @@ export type NamespaceWebTranslation = {
* Uncategorized
*/
unCategorized: string
+ /**
+ * Words Count
+ */
+ wordsCount: string
+ /**
+ * Reading Time
+ */
+ readingTime: string
}
info: {
/**
@@ -743,6 +751,14 @@ export type TranslationFunctions = {
* Uncategorized
*/
unCategorized: () => LocalizedString
+ /**
+ * Words Count
+ */
+ wordsCount: () => LocalizedString
+ /**
+ * Reading Time
+ */
+ readingTime: () => LocalizedString
}
info: {
/**
src/components/misc/PostInfo.astro
@@ -28,38 +28,54 @@ const {
...rest
} = Astro.props;
-const metas: ({ icon: string; text: string; link?: string; time?: Date } | undefined)[] = [
+interface MetaInfo {
+ text: string;
+ link?: string;
+ time?: Date;
+}
+
+const metas: (
+ | ({ icon: string; title?: string } & (MetaInfo | { group: MetaInfo[] }))
+ | undefined
+)[] = [
publishedAt && {
icon: 'material-symbols:calendar-clock-outline-rounded',
+ title: t.meta.publishedAt(),
text: publishedAt.toLocaleDateString(lang || siteConfig.lang.replace('_', '-')),
time: publishedAt,
},
articleConfig.wordCount && typeof wordCount === 'number'
? {
icon: 'material-symbols:docs-rounded',
+ title: t.meta.wordsCount(),
text: t.status.wordsCount(wordCount),
}
: undefined,
articleConfig.readingTime && typeof readingTime === 'number'
? {
icon: 'material-symbols:nest-clock-farsight-analog-rounded',
+ title: t.meta.readingTime(),
text: t.status.readTime(readingTime),
}
: undefined,
category
? {
icon: 'material-symbols:category-outline-rounded',
+ title: t.meta.category(),
text: category,
link: getCategoryUrl(category),
}
: undefined,
- ...(tags?.map((tag) => {
- return {
- icon: 'material-symbols:tag-rounded',
- text: tag,
- link: getTagUrl(tag),
- };
- }) || []),
+ tags && tags.length > 0
+ ? {
+ icon: 'material-symbols:tag-rounded',
+ title: t.meta.tags(),
+ group: tags.map((tag) => ({
+ text: tag,
+ link: getTagUrl(tag),
+ })),
+ }
+ : undefined,
];
---
@@ -71,21 +87,31 @@ const metas: ({ icon: string; text: string; link?: string; time?: Date } | undef
{metas.map((meta) => {
return (
meta && (
- <div class="text-base-content/60 flex items-center text-sm">
- <MetaIcon name={meta.icon} />
+ <div class="flex flex-wrap items-center gap-1">
+ <MetaIcon name={meta.icon} title={meta.title} aria-label={meta.title} />
{(() => {
- const text = meta.time ? (
- <time datetime={meta.time?.toISOString()}>{meta.text}</time>
- ) : (
- <span>{meta.text}</span>
- );
- return meta.link ? (
- <a href={meta.link} title={meta.text}>
- {text}
- </a>
- ) : (
- text
- );
+ const process = (info: MetaInfo) => {
+ const text = info.time ? (
+ <time datetime={info.time?.toISOString()}>{info.text}</time>
+ ) : (
+ <span>{info.text}</span>
+ );
+ return info.link ? (
+ <a href={info.link} title={info.text} class="link-hover">
+ {text}
+ </a>
+ ) : (
+ text
+ );
+ };
+ if ('group' in meta) {
+ return meta.group
+ .map(process)
+ .flatMap((item, index, arr) =>
+ index === arr.length - 1 ? [item] : [item, '/']
+ );
+ }
+ return process(meta);
})()}
</div>
)
src/components/widgets/MetaIcon.astro
@@ -14,7 +14,6 @@ const { class: className, ...rest } = Astro.props;
width: 1.5rem;
height: 1.5rem;
align-items: center;
- margin-right: 0.5rem;
display: flex;
justify-content: center;
color: color-mix(in oklab, var(--color-secondary) 80%, transparent);
src/components/widgets/PostCard.astro
@@ -1,6 +1,7 @@
---
import { siteConfig } from '@/config';
import { getCategoryUrl, getTagUrl } from '@utils/content-utils';
+import { t } from '@utils/i18n';
import type { ImageMetadata } from 'astro';
import MetaIcon from './MetaIcon.astro';
import PostCardCover from './PostCardCover.astro';
@@ -11,42 +12,51 @@ interface Props {
title: string;
url: string;
published: Date;
- updated?: Date;
tags: string[];
category?: string;
cover?: string | ImageMetadata;
description: string;
}
-const { title, url, published, updated, tags, category, cover } = Astro.props;
+const { title, url, published, tags, category, cover } = Astro.props;
const className = Astro.props.class;
const hasCover = cover !== '' && cover !== undefined && cover !== null;
-const metas: ({ icon: string; text: string; link?: string; time?: Date } | undefined)[] = [
+interface MetaInfo {
+ text: string;
+ link?: string;
+ time?: Date;
+}
+
+const metas: (
+ | ({ icon: string; title?: string } & (MetaInfo | { group: MetaInfo[] }))
+ | undefined
+)[] = [
{
icon: 'material-symbols:calendar-clock-outline-rounded',
+ title: t.meta.publishedAt(),
text: published.toLocaleDateString(siteConfig.lang.replace('_', '-')),
time: published,
},
- updated && {
- icon: 'material-symbols:edit-calendar-outline-rounded',
- text: updated.toLocaleDateString(siteConfig.lang.replace('_', '-')),
- },
category
? {
icon: 'material-symbols:category-outline-rounded',
+ title: t.meta.category(),
text: category,
link: getCategoryUrl(category),
}
: undefined,
- ...tags.map((tag) => {
- return {
- icon: 'material-symbols:tag-rounded',
- text: tag,
- link: getTagUrl(tag),
- };
- }),
+ tags.length > 0
+ ? {
+ icon: 'material-symbols:tag-rounded',
+ title: t.meta.tags(),
+ group: tags.map((tag) => ({
+ text: tag,
+ link: getTagUrl(tag),
+ })),
+ }
+ : undefined,
];
---
@@ -58,26 +68,36 @@ const metas: ({ icon: string; text: string; link?: string; time?: Date } | undef
>
<div class="card-body">
<a href={url} class="card-title">{title}</a>
- <div class="text-base-content/60 mb-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-sm">
+ <div class="text-base-content/60 mb-3 flex flex-wrap items-center gap-3 text-sm">
{
metas.map((meta) => {
return (
meta && (
- <div class="flex items-center gap-1">
- <MetaIcon name={meta.icon} />
+ <div class="flex flex-wrap items-center gap-1">
+ <MetaIcon name={meta.icon} title={meta.title} aria-label={meta.title} />
{(() => {
- const text = meta.time ? (
- <time datetime={meta.time?.toISOString()}>{meta.text}</time>
- ) : (
- <span>{meta.text}</span>
- );
- return meta.link ? (
- <a href={meta.link} title={meta.text}>
- {text}
- </a>
- ) : (
- text
- );
+ const process = (info: MetaInfo) => {
+ const text = info.time ? (
+ <time datetime={info.time?.toISOString()}>{info.text}</time>
+ ) : (
+ <span>{info.text}</span>
+ );
+ return info.link ? (
+ <a href={info.link} title={info.text} class="link-hover">
+ {text}
+ </a>
+ ) : (
+ text
+ );
+ };
+ if ('group' in meta) {
+ return meta.group
+ .map(process)
+ .flatMap((item, index, arr) =>
+ index === arr.length - 1 ? [item] : [item, '/']
+ );
+ }
+ return process(meta);
})()}
</div>
)