@@ -17,6 +17,26 @@ import type { JsDelivrFileNode } from '#shared/types'
1717import { joinURL } from ' ufo'
1818import { smoothPath , useCharts } from ' ~/composables/useCharts'
1919
20+ const REPO_PROVIDER_ICONS: Record <string , string > = {
21+ github: ' i-simple-icons:github' ,
22+ gitlab: ' i-simple-icons:gitlab' ,
23+ bitbucket: ' i-simple-icons:bitbucket' ,
24+ codeberg: ' i-simple-icons:codeberg' ,
25+ gitea: ' i-simple-icons:gitea' ,
26+ forgejo: ' i-simple-icons:forgejo' ,
27+ gitee: ' i-simple-icons:gitee' ,
28+ sourcehut: ' i-simple-icons:sourcehut' ,
29+ tangled: ' i-custom:tangled' ,
30+ radicle: ' i-lucide:network' ,
31+ }
32+
33+ function sortJsDelivrNodes(nodes : JsDelivrFileNode []) {
34+ return [... nodes ].sort ((a , b ) => {
35+ if (a .type !== b .type ) return a .type === ' directory' ? - 1 : 1
36+ return a .name .localeCompare (b .name )
37+ })
38+ }
39+
2040const { name, version, variant } = defineProps <{
2141 name: string
2242 version: string | null
@@ -55,6 +75,10 @@ const repositoryUrl = computed(() => {
5575})
5676
5777const { repoRef, stars, refresh : refreshRepoMeta } = useRepoMeta (repositoryUrl )
78+ const repoProviderIcon = computed (() => {
79+ const provider = repoRef .value ?.provider
80+ return provider ? (REPO_PROVIDER_ICONS [provider ] ?? ' i-lucide:code' ) : ' i-lucide:code'
81+ })
5882
5983const formattedStars = computed (() => (stars .value > 0 ? compactFormat .format (stars .value ) : ' ' ))
6084
@@ -104,22 +128,15 @@ async function fetchCodeTree() {
104128 // Call jsDelivr directly — $fetch to internal API can deadlock in OG image island context
105129 const resp = await $fetch <{ files: JsDelivrFileNode [] }>(
106130 ` https://data.jsdelivr.com/v1/packages/npm/${name }@${ver } ` ,
131+ { timeout: 3000 },
107132 ).catch (() => null )
108133 if (! resp ?.files ) return
109134
110135 const rows: TreeRow [] = []
111136 const MAX_ROWS = 25
112137
113- // Sort: directories first, then files, alphabetical within each group
114- function sorted(nodes : JsDelivrFileNode []) {
115- return [... nodes ].sort ((a , b ) => {
116- if (a .type !== b .type ) return a .type === ' directory' ? - 1 : 1
117- return a .name .localeCompare (b .name )
118- })
119- }
120-
121138 function walk(nodes : JsDelivrFileNode [], depth : number ) {
122- for (const node of sorted (nodes )) {
139+ for (const node of sortJsDelivrNodes (nodes )) {
123140 if (rows .length >= MAX_ROWS ) return
124141 rows .push ({ name: node .name , depth , isDir: node .type === ' directory' })
125142 if (node .files ) walk (node .files , depth + 1 )
@@ -275,7 +292,7 @@ const sparklineSrc = computed(() => {
275292 <div class =" flex flex-col gap-3 text-4xl text-fg-muted" >
276293 <div v-if =" repositoryUrl" class =" flex items-center gap-2" >
277294 <div
278- class =" i-simple-icons:github shrink-0 text-fg-muted"
295+ : class =" [repoProviderIcon, ' shrink-0 text-fg-muted'] "
279296 style =" width : 24px ; height : 24px "
280297 />
281298 <span v-if =" repoRef" class =" max-w-[500px]" style =" text-overflow : ellipsis " >
0 commit comments