master
1---
2import MetaIcon from '@components/widgets/MetaIcon.astro';
3import type { HTMLAttributes } from 'astro/types';
4
5interface MetaInfo {
6 text: string;
7 link?: string;
8 time?: Date;
9}
10
11interface MetaIconInfo {
12 icon: string;
13 title?: string;
14}
15
16export type MetaItem = (MetaIconInfo & (MetaInfo | { group: MetaInfo[] })) | undefined;
17
18interface Props extends HTMLAttributes<'div'> {
19 metas: MetaItem[];
20}
21
22const { metas, class: className, ...rest } = Astro.props;
23---
24
25{
26 metas.filter((item) => Boolean(item)).length > 0 && (
27 <div class:list={['flex flex-wrap gap-x-3 gap-y-2', className]} {...rest}>
28 {metas.map((meta) => {
29 return (
30 meta && (
31 <div class="flex flex-wrap items-center gap-1">
32 <MetaIcon name={meta.icon} title={meta.title} aria-label={meta.title} />
33 {(() => {
34 const process = (info: MetaInfo) => {
35 const text = info.time ? (
36 <time datetime={info.time?.toISOString()}>{info.text}</time>
37 ) : (
38 <span>{info.text}</span>
39 );
40 return info.link ? (
41 <a href={info.link} title={info.text} class="link-hover not-hover:link">
42 {text}
43 </a>
44 ) : (
45 text
46 );
47 };
48 if ('group' in meta) {
49 return meta.group
50 .map(process)
51 .flatMap((item, index, arr) =>
52 index === arr.length - 1 ? [item] : [item, '/']
53 );
54 }
55 return process(meta);
56 })()}
57 </div>
58 )
59 );
60 })}
61 </div>
62 )
63}