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}