elk/components/status/StatusPreviewGitHub.vue

136 lines
3.8 KiB
Vue
Raw Normal View History

2022-12-17 21:11:39 +00:00
<script setup lang="ts">
2023-01-08 06:21:09 +00:00
import type { mastodon } from 'masto'
2022-12-17 21:11:39 +00:00
const props = defineProps<{
2023-01-08 06:21:09 +00:00
card: mastodon.v1.PreviewCard
2022-12-17 21:11:39 +00:00
}>()
type UrlType = 'user' | 'repo' | 'issue' | 'pull'
interface Meta {
type: UrlType
user?: string
titleUrl: string
2022-12-17 21:11:39 +00:00
avatar: string
details: string
repo?: string
number?: string
author?: {
avatar: string
user: string
2022-12-17 21:11:39 +00:00
}
}
const specialRoutes = ['orgs', 'sponsors', 'stars']
2022-12-17 21:11:39 +00:00
const meta = $computed(() => {
const { url } = props.card
const path = url.split('https://github.com/')[1]
// Supported paths
// /user
// /user/repo
// /user/repo/issues/number
// /user/repo/pull/number
// /orgs/user
// /sponsors/user
// /stars/user
const firstName = path.match(/([\w-]+)(\/|$)/)?.[1]
const secondName = path.match(/[\w-]+\/([\w-]+)/)?.[1]
const firstIsUser = firstName && !specialRoutes.includes(firstName)
const user = firstIsUser ? firstName : secondName
const repo = firstIsUser ? secondName : undefined
2022-12-17 21:11:39 +00:00
let type: UrlType = repo ? 'repo' : 'user'
let number: string | undefined
let details = (props.card.title ?? '').replace('GitHub - ', '').split(' · ')[0]
if (repo) {
const repoPath = `${user}/${repo}`
details = details.replace(`${repoPath}: `, '')
const inRepoPath = path.split(`${repoPath}/`)?.[1]
if (inRepoPath) {
number = inRepoPath.match(/issues\/(\d+)/)?.[1]
if (number) {
type = 'issue'
}
else {
number = inRepoPath.match(/pull\/(\d+)/)?.[1]
if (number)
type = 'pull'
}
2022-12-17 21:11:39 +00:00
}
}
const avatar = `https://github.com/${user}.png?size=256`
const author = props.card.authorName
2022-12-17 21:11:39 +00:00
const info = $ref<Meta>({
type,
user,
titleUrl: `https://github.com/${user}${repo ? `/${repo}` : ''}`,
2022-12-17 21:11:39 +00:00
details,
repo,
number,
avatar,
author: author
? {
avatar: `https://github.com/${author}.png?size=64`,
user: author,
}
: undefined,
2022-12-17 21:11:39 +00:00
})
return info
})
</script>
<template>
<div
v-if="card.image"
flex flex-col
display-block of-hidden
2023-01-10 09:05:59 +00:00
bg-card
2022-12-17 21:11:39 +00:00
relative
2023-01-09 22:29:03 +00:00
w-full min-h-50 md:min-h-60
justify-center
rounded-lg
2022-12-17 21:11:39 +00:00
>
<div p4 sm:px-8 flex flex-col justify-between min-h-50 md:min-h-60 h-full>
<div flex justify-between items-center gap-2 sm:gap-6 h-full mb-2 min-h-35 md:min-h-45>
2022-12-17 21:11:39 +00:00
<div flex flex-col gap-2>
<NuxtLink flex gap-1 text-xl sm:text-3xl flex-wrap leading-none :href="meta.titleUrl" target="_blank" external>
2022-12-17 21:11:39 +00:00
<template v-if="meta.repo">
<span>{{ meta.user }}</span><span text-secondary-light>/</span><span text-primary font-bold>{{ meta.repo }}</span>
</template>
<span v-else>{{ meta.user }}</span>
</NuxtLink>
<NuxtLink sm:text-lg :href="card.url" target="_blank" external>
<span v-if="meta.type === 'issue'" text-secondary-light me-2>
2022-12-18 10:26:55 +00:00
#{{ meta.number }}
</span>
<span v-if="meta.type === 'pull'" text-secondary-light me-2>
2022-12-17 21:11:39 +00:00
PR #{{ meta.number }}
2022-12-18 10:26:55 +00:00
</span>
<span text-secondary leading-tight>{{ meta.details }}</span>
</NuxtLink>
2022-12-17 21:11:39 +00:00
</div>
<div shrink-0 w-18 sm:w-30>
<NuxtLink :href="meta.titleUrl" target="_blank" external>
<img w-full aspect-square width="112" height="112" rounded-2 :src="meta.avatar">
</NuxtLink>
2022-12-17 21:11:39 +00:00
</div>
</div>
<div flex justify-between>
<div v-if="meta.author" flex class="gap-2.5" items-center>
2022-12-17 21:11:39 +00:00
<div>
<img w-8 aspect-square width="25" height="25" rounded-full :src="meta.author?.avatar">
2022-12-17 21:11:39 +00:00
</div>
<span text-lg text-primary>@{{ meta.author?.user }}</span>
2022-12-17 21:11:39 +00:00
</div>
<div v-else />
<div text-3xl i-ri:github-fill text-secondary />
2022-12-17 21:11:39 +00:00
</div>
</div>
</div>
</template>