Skip to content

Commit 90aadf8

Browse files
committed
fix: show version-specific license, no-deps empty state, layout stability (#2163, #2168, #2190, #1826)
1 parent 7f2fc1a commit 90aadf8

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

app/components/Package/Dependencies.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ const numberFormatter = useNumberFormatter()
9494

9595
<template>
9696
<div class="space-y-8">
97+
<!-- Empty state when no dependencies at all -->
98+
<p
99+
v-if="sortedDependencies.length === 0 && sortedPeerDependencies.length === 0 && sortedOptionalDependencies.length === 0"
100+
class="text-sm text-fg-subtle"
101+
>
102+
{{ $t('package.dependencies.none') }}
103+
</p>
104+
97105
<!-- Dependencies -->
98106
<CollapsibleSection
99107
v-if="sortedDependencies.length > 0"

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

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,27 @@ function prefetchReadmeMarkdown() {
108108
}
109109
110110
async function copyReadmeHandler() {
111-
await fetchReadmeMarkdown()
111+
// Safari requires navigator.clipboard.write() to be called synchronously within
112+
// the user gesture, but accepts a Promise inside ClipboardItem.
113+
// This pattern works in Safari 13.1+, Chrome, and Firefox.
114+
if (typeof ClipboardItem !== 'undefined' && navigator.clipboard?.write) {
115+
const blobPromise = (async () => {
116+
await fetchReadmeMarkdown()
117+
const markdown = readmeMarkdownData.value?.markdown ?? ''
118+
return new Blob([markdown], { type: 'text/plain' })
119+
})()
120+
try {
121+
await navigator.clipboard.write([new ClipboardItem({ 'text/plain': blobPromise })])
122+
return
123+
} catch {
124+
// Fall through to legacy approach
125+
}
126+
}
112127
128+
// Legacy fallback (non-Safari, or older browsers)
129+
await fetchReadmeMarkdown()
113130
const markdown = readmeMarkdownData.value?.markdown
114131
if (!markdown) return
115-
116132
await copyReadme(markdown)
117133
}
118134
@@ -305,6 +321,17 @@ const latestVersion = computed(() => {
305321
return pkg.value.versions[latestTag] ?? null
306322
})
307323
324+
// Detect license changes between current version and latest
325+
const licenseChanged = computed(() => {
326+
const currentLicense = displayVersion.value?.license
327+
const latestLicense = latestVersion.value?.license ?? pkg.value?.license
328+
if (!currentLicense || !latestLicense) return false
329+
// Normalize: compare string representations
330+
const normalize = (l: unknown): string =>
331+
typeof l === 'string' ? l : (l as { type?: string })?.type ?? ''
332+
return normalize(currentLicense) !== normalize(latestLicense)
333+
})
334+
308335
const deprecationNotice = computed(() => {
309336
if (!displayVersion.value?.deprecated) return null
310337
@@ -582,9 +609,19 @@ const showSkeleton = shallowRef(false)
582609
<dt class="text-xs text-fg-subtle uppercase tracking-wider">
583610
{{ $t('package.stats.license') }}
584611
</dt>
585-
<dd class="font-mono text-sm text-fg">
586-
<LicenseDisplay v-if="pkg.license" :license="pkg.license" />
612+
<dd class="font-mono text-sm text-fg flex items-center gap-2 flex-wrap">
613+
<LicenseDisplay v-if="displayVersion?.license ?? pkg.license" :license="displayVersion?.license ?? pkg.license" />
587614
<span v-else>{{ $t('package.license.none') }}</span>
615+
<TooltipApp
616+
v-if="licenseChanged"
617+
:text="$t('package.license.changed', { latest: latestVersion?.license ?? pkg.license })"
618+
position="bottom"
619+
>
620+
<span class="inline-flex items-center gap-1 px-1.5 py-0.5 text-2xs font-sans rounded bg-amber-500/15 text-amber-700 dark:text-amber-400 border border-amber-500/30 cursor-help">
621+
<span class="i-lucide:triangle-alert w-3 h-3" aria-hidden="true" />
622+
{{ $t('package.license.changed_badge') }}
623+
</span>
624+
</TooltipApp>
588625
</dd>
589626
</div>
590627

@@ -959,7 +996,7 @@ const showSkeleton = shallowRef(false)
959996

960997
<!-- Dependencies -->
961998
<PackageDependencies
962-
v-if="hasDependencies && resolvedVersion && displayVersion"
999+
v-if="resolvedVersion && displayVersion"
9631000
:package-name="pkg.name"
9641001
:version="resolvedVersion"
9651002
:dependencies="displayVersion.dependencies"
@@ -1107,7 +1144,7 @@ const showSkeleton = shallowRef(false)
11071144
'install sidebar'
11081145
'vulns sidebar'
11091146
'readme sidebar';
1110-
grid-template-rows: auto auto auto auto 1fr;
1147+
grid-template-rows: auto auto auto auto;
11111148
}
11121149
}
11131150
@@ -1159,6 +1196,7 @@ const showSkeleton = shallowRef(false)
11591196
11601197
.areaSidebar {
11611198
grid-area: sidebar;
1199+
align-self: start;
11621200
}
11631201
11641202
@media (max-width: 639.9px) {

0 commit comments

Comments
 (0)