11<script setup lang="ts">
2+ import { parseDependencyVersion } from ' #shared/utils/npm'
23import { SEVERITY_TEXT_COLORS , getHighestSeverity } from ' #shared/utils/severity'
34import { getOutdatedTooltip , getVersionClass } from ' ~/utils/npm/outdated-dependencies'
45
@@ -66,24 +67,41 @@ const sortedOptionalDependencies = computed(() => {
6667 return Object .entries (props .optionalDependencies ).sort (([a ], [b ]) => a .localeCompare (b ))
6768})
6869
69- // Get version tooltip
70- function getDepVersionTooltip(dep : string , version : string ) {
71- const outdated = outdatedDeps .value [dep ]
70+ // Get version tooltip (key for outdated lookup, realName for vuln/replacement lookup)
71+ function getDepVersionTooltip(key : string , realName : string , version : string ) {
72+ const outdated = outdatedDeps .value [key ]
7273 if (outdated ) return getOutdatedTooltip (outdated , t )
73- if (getVulnerableDepInfo (dep ) || getDeprecatedDepInfo (dep )) return version
74- if (replacementDeps .value [dep ]) return t (' package.dependencies.has_replacement' )
74+ if (getVulnerableDepInfo (realName ) || getDeprecatedDepInfo (realName )) return version
75+ if (replacementDeps .value [realName ]) return t (' package.dependencies.has_replacement' )
7576 return version
7677}
7778
78- // Get version class
79- function getDepVersionClass(dep : string ) {
80- const outdated = outdatedDeps .value [dep ]
79+ // Get version class (key for outdated lookup, realName for vuln/replacement lookup)
80+ function getDepVersionClass(key : string , realName : string ) {
81+ const outdated = outdatedDeps .value [key ]
8182 if (outdated ) return getVersionClass (outdated )
82- if (replacementDeps .value [dep ]) return ' text-amber-700 dark:text-amber-500'
83- if (getVulnerableDepInfo (dep ) || getDeprecatedDepInfo (dep )) return getVersionClass (undefined )
83+ if (getVulnerableDepInfo (realName ) || getDeprecatedDepInfo (realName ))
84+ return getVersionClass (undefined )
85+ if (replacementDeps .value [realName ]) return ' text-amber-700 dark:text-amber-500'
8486 return getVersionClass (undefined )
8587}
8688
89+ // Resolve npm: aliases — returns the real package name for links
90+ function resolveDepName(key : string , value : string ): string {
91+ return parseDependencyVersion (value ).name ?? key
92+ }
93+
94+ // Resolve npm: aliases — returns the version range for display
95+ function depRange(value : string ): string {
96+ return parseDependencyVersion (value ).range ?? value
97+ }
98+
99+ // Whether a dependency uses an npm: alias (listed name differs from the real package)
100+ function isAliased(key : string , value : string ): boolean {
101+ const realName = parseDependencyVersion (value ).name
102+ return realName != null && realName !== key
103+ }
104+
87105const {
88106 visibleItems : visibleDeps,
89107 hasMore : hasMoreDeps,
@@ -127,10 +145,29 @@ const numberFormatter = useNumberFormatter()
127145 :key =" dep"
128146 class =" flex items-center justify-between py-1 text-sm gap-2"
129147 >
130- <LinkBase :to =" packageRoute (dep )" class="block truncate" dir="ltr">
148+ <LinkBase
149+ :to =" packageRoute (resolveDepName (dep , version ))"
150+ class="block truncate"
151+ dir="ltr"
152+ >
131153 {{ dep }}
132154 </LinkBase >
133155 <span class =" flex items-center gap-1 max-w-[40%]" dir =" ltr" >
156+ <TooltipApp
157+ v-if =" isAliased (dep , version )"
158+ class="shrink-0 text-fg-muted"
159+ :text =" $t (' package.dependencies.aliased_to' , { name: resolveDepName (dep , version ) })"
160+ >
161+ <button
162+ type =" button"
163+ class =" inline-flex items-center justify-center p-2 -m-2"
164+ :aria-label ="
165+ $t('package.dependencies.aliased_to', { name: resolveDepName(dep, version) })
166+ "
167+ >
168+ <span class =" i-lucide:arrow-right-left w-3 h-3" aria-hidden =" true" />
169+ </button >
170+ </TooltipApp >
134171 <TooltipApp
135172 v-if =" outdatedDeps [dep ]"
136173 class="shrink-0"
@@ -146,7 +183,7 @@ const numberFormatter = useNumberFormatter()
146183 </button >
147184 </TooltipApp >
148185 <TooltipApp
149- v-if =" replacementDeps [dep ]"
186+ v-if =" replacementDeps [resolveDepName ( dep , version ) ]"
150187 class="shrink-0 text-amber-700 dark:text-amber-500 "
151188 :text =" $t (' package.dependencies.has_replacement' )"
152189 >
@@ -159,41 +196,55 @@ const numberFormatter = useNumberFormatter()
159196 </button >
160197 </TooltipApp >
161198 <LinkBase
162- v-if =" getVulnerableDepInfo (dep )"
163- :to =" packageRoute (dep , getVulnerableDepInfo (dep )! .version )"
199+ v-if =" getVulnerableDepInfo (resolveDepName (dep , version ))"
200+ :to ="
201+ packageRoute (
202+ resolveDepName (dep , version ),
203+ getVulnerableDepInfo (resolveDepName (dep , version ))! .version ,
204+ )
205+ "
164206 class="shrink-0"
165- :class =" SEVERITY_TEXT_COLORS [getHighestSeverity (getVulnerableDepInfo (dep )! .counts )]"
207+ :class ="
208+ SEVERITY_TEXT_COLORS [
209+ getHighestSeverity (getVulnerableDepInfo (resolveDepName (dep , version ))! .counts )
210+ ]
211+ "
166212 :aria-label =" $t (' package.dependencies.view_vulnerabilities' )"
167213 :title ="
168214 $t (' package.dependencies.vulnerabilities_count' , {
169- count: getVulnerableDepInfo (dep )! .counts .total ,
215+ count: getVulnerableDepInfo (resolveDepName ( dep , version ) )! .counts .total ,
170216 })
171217 "
172218 classicon="i-lucide:shield-check "
173219 />
174220 <LinkBase
175- v-if =" getDeprecatedDepInfo (dep )"
176- :to =" packageRoute (dep , getDeprecatedDepInfo (dep )! .version )"
221+ v-if =" getDeprecatedDepInfo (resolveDepName (dep , version ))"
222+ :to ="
223+ packageRoute (
224+ resolveDepName (dep , version ),
225+ getDeprecatedDepInfo (resolveDepName (dep , version ))! .version ,
226+ )
227+ "
177228 class="shrink-0 text-purple-700 dark:text-purple-500 "
178229 :aria-label =" $t (' package.deprecated.label' )"
179- :title =" getDeprecatedDepInfo (dep )! .message "
230+ :title =" getDeprecatedDepInfo (resolveDepName ( dep , version ) )! .message "
180231 classicon="i-lucide:octagon-alert "
181232 />
182233 <LinkBase
183- :to =" packageRoute (dep , version )"
234+ :to =" packageRoute (resolveDepName ( dep , version ), depRange ( version ) )"
184235 class="block truncate"
185- :class =" getDepVersionClass (dep )"
186- :title =" getDepVersionTooltip (dep , version )"
236+ :class =" getDepVersionClass (dep , resolveDepName ( dep , version ) )"
237+ :title =" getDepVersionTooltip (dep , resolveDepName ( dep , version ), depRange ( version ) )"
187238 >
188- {{ version }}
239+ {{ depRange( version) }}
189240 </LinkBase >
190241 <span v-if =" outdatedDeps[dep]" class =" sr-only" >
191242 ({{ getOutdatedTooltip(outdatedDeps[dep], $t) }})
192243 </span >
193- <span v-if =" getVulnerableDepInfo(dep)" class =" sr-only" >
244+ <span v-if =" getVulnerableDepInfo(resolveDepName( dep, version) )" class =" sr-only" >
194245 ({{
195246 $t('package.dependencies.vulnerabilities_count', {
196- count: getVulnerableDepInfo(dep)!.counts.total,
247+ count: getVulnerableDepInfo(resolveDepName( dep, version) )!.counts.total,
197248 })
198249 }})
199250 </span >
@@ -238,7 +289,11 @@ const numberFormatter = useNumberFormatter()
238289 class =" flex items-center justify-between py-1 text-sm gap-1 min-w-0"
239290 >
240291 <div class =" flex items-center gap-2 min-w-0 flex-1" >
241- <LinkBase :to =" packageRoute (peer .name )" class="block min-w-0 break-all" dir="ltr">
292+ <LinkBase
293+ :to =" packageRoute (resolveDepName (peer .name , peer .version ))"
294+ class="block min-w-0 break-all"
295+ dir="ltr"
296+ >
242297 {{ peer.name }}
243298 </LinkBase >
244299 <TagStatic
@@ -250,12 +305,12 @@ const numberFormatter = useNumberFormatter()
250305 </TagStatic >
251306 </div >
252307 <LinkBase
253- :to =" packageRoute (peer .name , peer .version )"
308+ :to =" packageRoute (resolveDepName ( peer .name , peer .version ), depRange ( peer . version ) )"
254309 class="block truncate shrink-0 max-w-20"
255- :title =" peer .version "
310+ :title =" depRange ( peer .version ) "
256311 dir="ltr"
257312 >
258- {{ peer.version }}
313+ {{ depRange( peer.version) }}
259314 </LinkBase >
260315 </li >
261316 </ul >
@@ -300,17 +355,38 @@ const numberFormatter = useNumberFormatter()
300355 :key =" dep"
301356 class =" flex items-baseline justify-between py-1 text-sm gap-2"
302357 >
303- <LinkBase :to =" packageRoute (dep )" class="block max-w-[80%] break-words" dir="ltr">
304- {{ dep }}
305- </LinkBase >
306358 <LinkBase
307- :to =" packageRoute (dep , version )"
308- class="block truncate"
309- :title =" version "
359+ :to =" packageRoute (resolveDepName (dep , version ))"
360+ class="block max-w-[80%] break-words"
310361 dir="ltr"
311362 >
312- {{ version }}
363+ {{ dep }}
313364 </LinkBase >
365+ <span class =" flex items-center gap-1 min-w-0" dir =" ltr" >
366+ <TooltipApp
367+ v-if =" isAliased (dep , version )"
368+ class="shrink-0 text-fg-muted"
369+ :text =" $t (' package.dependencies.aliased_to' , { name: resolveDepName (dep , version ) })"
370+ >
371+ <button
372+ type =" button"
373+ class =" inline-flex items-center justify-center p-2 -m-2"
374+ :aria-label ="
375+ $t('package.dependencies.aliased_to', { name: resolveDepName(dep, version) })
376+ "
377+ >
378+ <span class =" i-lucide:arrow-right-left w-3 h-3" aria-hidden =" true" />
379+ </button >
380+ </TooltipApp >
381+ <LinkBase
382+ :to =" packageRoute (resolveDepName (dep , version ), depRange (version ))"
383+ class="block truncate"
384+ :title =" depRange (version )"
385+ dir="ltr"
386+ >
387+ {{ depRange(version) }}
388+ </LinkBase >
389+ </span >
314390 </li >
315391 </ul >
316392 <button
0 commit comments