Skip to content

Commit b355773

Browse files
committed
feat: link to releases
1 parent 344fd65 commit b355773

File tree

8 files changed

+562
-115
lines changed

8 files changed

+562
-115
lines changed

app/components/Package/Versions.vue

Lines changed: 202 additions & 111 deletions
Large diffs are not rendered by default.

app/composables/useRepoMeta.ts

Lines changed: 239 additions & 0 deletions
Large diffs are not rendered by default.

app/pages/package/[[org]]/[name].vue

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { detectPublishSecurityDowngradeForVersion } from '~/utils/publish-securi
1717
import { useModal } from '~/composables/useModal'
1818
import { useAtproto } from '~/composables/atproto/useAtproto'
1919
import { togglePackageLike } from '~/utils/atproto/likes'
20+
import { getMatchedRelease } from '~/utils/releases'
2021
2122
defineOgImageComponent('Package', {
2223
name: () => packageName.value,
@@ -358,7 +359,23 @@ const repositoryUrl = computed(() => {
358359
return url
359360
})
360361
361-
const { meta: repoMeta, repoRef, stars, starsLink, forks, forksLink } = useRepoMeta(repositoryUrl)
362+
const {
363+
meta: repoMeta,
364+
repoRef,
365+
stars,
366+
starsLink,
367+
forks,
368+
forksLink,
369+
releases,
370+
releasesLink,
371+
releasesPending,
372+
} = useRepoMeta(repositoryUrl)
373+
374+
const currentVersionRelease = computed(() => {
375+
const version = resolvedVersion.value ?? displayVersion.value?.version
376+
if (!version || !releases.value.length) return null
377+
return getMatchedRelease(version, releases.value)
378+
})
362379
363380
const PROVIDER_ICONS: Record<string, string> = {
364381
github: 'i-carbon:logo-github',
@@ -591,6 +608,16 @@ onKeyStroke(
591608
},
592609
)
593610
611+
onKeyStroke(
612+
e => isKeyWithoutModifiers(e, 'r') && !isEditableElement(e.target),
613+
e => {
614+
if (!currentVersionRelease.value) return
615+
e.preventDefault()
616+
navigateTo(currentVersionRelease.value.url)
617+
},
618+
{ dedupe: true },
619+
)
620+
594621
const showSkeleton = shallowRef(false)
595622
</script>
596623

@@ -734,6 +761,15 @@ const showSkeleton = shallowRef(false)
734761
>
735762
{{ $t('package.links.compare') }}
736763
</LinkBase>
764+
<LinkBase
765+
v-if="currentVersionRelease"
766+
variant="button-secondary"
767+
:to="currentVersionRelease.url"
768+
aria-keyshortcuts="r"
769+
classicon="i-carbon-catalog"
770+
>
771+
{{ $t('package.links.release') }}
772+
</LinkBase>
737773
</ButtonGroup>
738774

739775
<!-- Package metrics -->
@@ -1334,6 +1370,7 @@ const showSkeleton = shallowRef(false)
13341370
:dist-tags="pkg['dist-tags'] ?? {}"
13351371
:time="pkg.time"
13361372
:selected-version="resolvedVersion ?? pkg['dist-tags']?.['latest']"
1373+
:releases="releases"
13371374
/>
13381375

13391376
<!-- Install Scripts Warning -->

app/utils/releases.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { Release } from '~/composables/useRepoMeta'
2+
3+
/**
4+
* Match an npm version string to a repository release.
5+
* Handles various tag formats: "v1.0.0", "1.0.0", "release-1.0.0", etc.
6+
*
7+
* @param version - npm version string (e.g., "1.2.3", "0.9.0-beta.1")
8+
* @param releases - Array of releases from repository
9+
* @returns Matched release or null
10+
*/
11+
export function getMatchedRelease(version: string, releases: Release[]): Release | null {
12+
if (!version || !releases.length) return null
13+
14+
// Normalize version for comparison (remove any existing 'v' prefix)
15+
const normalizedVersion = version.replace(/^v/, '').toLowerCase()
16+
17+
// Try exact matches with common tag formats
18+
const tagVariants = [
19+
`v${normalizedVersion}`, // Most common: v1.0.0
20+
normalizedVersion, // Without prefix: 1.0.0
21+
`release-${normalizedVersion}`, // Some projects: release-1.0.0
22+
`${normalizedVersion}-release`, // Alternative: 1.0.0-release
23+
]
24+
25+
for (const release of releases) {
26+
if (!release.url) continue
27+
const releaseTag = release.tag.toLowerCase()
28+
29+
// Check each variant (case-insensitive)
30+
for (const variant of tagVariants) {
31+
if (releaseTag === variant) {
32+
return release
33+
}
34+
}
35+
}
36+
37+
return null
38+
}

i18n/locales/en.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,14 @@
206206
"code": "code",
207207
"docs": "docs",
208208
"fund": "fund",
209-
"compare": "compare"
209+
"compare": "compare",
210+
"release": "release"
211+
},
212+
"releases": {
213+
"title": "Releases",
214+
"view_all": "View all {count} releases",
215+
"view_release": "View release",
216+
"view_release_for_version": "View release for {version}"
210217
},
211218
"likes": {
212219
"like": "Like this package",

i18n/schema.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,27 @@
624624
},
625625
"compare": {
626626
"type": "string"
627+
},
628+
"release": {
629+
"type": "string"
630+
}
631+
},
632+
"additionalProperties": false
633+
},
634+
"releases": {
635+
"type": "object",
636+
"properties": {
637+
"title": {
638+
"type": "string"
639+
},
640+
"view_all": {
641+
"type": "string"
642+
},
643+
"view_release": {
644+
"type": "string"
645+
},
646+
"view_release_for_version": {
647+
"type": "string"
627648
}
628649
},
629650
"additionalProperties": false

lunaria/files/en-GB.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,14 @@
205205
"code": "code",
206206
"docs": "docs",
207207
"fund": "fund",
208-
"compare": "compare"
208+
"compare": "compare",
209+
"release": "release"
210+
},
211+
"releases": {
212+
"title": "Releases",
213+
"view_all": "View all {count} releases",
214+
"view_release": "View release",
215+
"view_release_for_version": "View release for {version}"
209216
},
210217
"likes": {
211218
"like": "Like this package",

lunaria/files/en-US.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,14 @@
205205
"code": "code",
206206
"docs": "docs",
207207
"fund": "fund",
208-
"compare": "compare"
208+
"compare": "compare",
209+
"release": "release"
210+
},
211+
"releases": {
212+
"title": "Releases",
213+
"view_all": "View all {count} releases",
214+
"view_release": "View release",
215+
"view_release_for_version": "View release for {version}"
209216
},
210217
"likes": {
211218
"like": "Like this package",

0 commit comments

Comments
 (0)