Skip to content

Commit 40417fb

Browse files
committed
perf: use vue router to parse package page paths
1 parent bf55ec9 commit 40417fb

8 files changed

Lines changed: 37 additions & 61 deletions

File tree

app/components/PackageCard.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const emit = defineEmits<{
2727
class="font-mono text-sm sm:text-base font-medium text-fg group-hover:text-fg transition-colors duration-200 min-w-0 break-all"
2828
>
2929
<NuxtLink
30-
:to="{ name: 'package', params: { package: result.package.name.split('/') } }"
30+
:to="{ name: 'package', params: parsePackageRouteParams(result.package.name) }"
3131
:prefetch-on="prefetch ? 'visibility' : 'interaction'"
3232
class="focus-visible:outline-none decoration-none scroll-mt-48 scroll-mb-6 after:content-[''] after:absolute after:inset-0"
3333
:data-result-index="index"

app/components/PackageDependencies.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const sortedOptionalDependencies = computed(() => {
5959
class="flex items-center justify-between py-1 text-sm gap-2"
6060
>
6161
<NuxtLink
62-
:to="{ name: 'package', params: { package: dep.split('/') } }"
62+
:to="{ name: 'package', params: parsePackageRouteParams(dep) }"
6363
class="font-mono text-fg-muted hover:text-fg transition-colors duration-200 truncate min-w-0"
6464
>
6565
{{ dep }}
@@ -75,7 +75,7 @@ const sortedOptionalDependencies = computed(() => {
7575
<span class="i-carbon-warning-alt w-3 h-3 block" />
7676
</span>
7777
<NuxtLink
78-
:to="{ name: 'package', params: { package: [...dep.split('/'), 'v', version] } }"
78+
:to="{ name: 'package', params: { ...parsePackageRouteParams(dep), version } }"
7979
class="font-mono text-xs text-right truncate"
8080
:class="getVersionClass(outdatedDeps[dep])"
8181
:title="outdatedDeps[dep] ? getOutdatedTooltip(outdatedDeps[dep]) : version"
@@ -114,7 +114,7 @@ const sortedOptionalDependencies = computed(() => {
114114
>
115115
<div class="flex items-center gap-2 min-w-0">
116116
<NuxtLink
117-
:to="{ name: 'package', params: { package: peer.name.split('/') } }"
117+
:to="{ name: 'package', params: parsePackageRouteParams(peer.name) }"
118118
class="font-mono text-fg-muted hover:text-fg transition-colors duration-200 truncate"
119119
>
120120
{{ peer.name }}
@@ -170,13 +170,13 @@ const sortedOptionalDependencies = computed(() => {
170170
class="flex items-center justify-between py-1 text-sm gap-2"
171171
>
172172
<NuxtLink
173-
:to="{ name: 'package', params: { package: dep.split('/') } }"
173+
:to="{ name: 'package', params: parsePackageRouteParams(dep) }"
174174
class="font-mono text-fg-muted hover:text-fg transition-colors duration-200 truncate min-w-0"
175175
>
176176
{{ dep }}
177177
</NuxtLink>
178178
<NuxtLink
179-
:to="{ name: 'package', params: { package: [...dep.split('/'), 'v', version] } }"
179+
:to="{ name: 'package', params: { ...parsePackageRouteParams(dep), version } }"
180180
class="font-mono text-xs text-fg-subtle max-w-[50%] text-right truncate"
181181
:title="version"
182182
>

app/components/PackageInstallScripts.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const isExpanded = shallowRef(false)
6969
class="flex items-center justify-between py-0.5 text-sm gap-2"
7070
>
7171
<NuxtLink
72-
:to="{ name: 'package', params: { package: dep.split('/') } }"
72+
:to="{ name: 'package', params: parsePackageRouteParams(dep) }"
7373
class="font-mono text-fg-muted hover:text-fg transition-colors duration-200 truncate min-w-0"
7474
>
7575
{{ dep }}

app/components/PackageVersions.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function hasProvenance(version: PackumentVersion | undefined): boolean {
4040
function versionRoute(version: string): RouteLocationRaw {
4141
return {
4242
name: 'package',
43-
params: { package: [...props.packageName.split('/'), 'v', version] },
43+
params: { ...parsePackageRouteParams(props.packageName), version },
4444
}
4545
}
4646

app/composables/usePackageRoute.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function parsePackageRouteParams(pkg: string) {
2+
const [org, name] = pkg.startsWith('@') ? pkg.split('/') : [null, pkg]
3+
4+
return { org, name }
5+
}

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

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,65 +8,37 @@ import { areUrlsEquivalent } from '#shared/utils/url'
88
99
definePageMeta({
1010
name: 'package',
11-
alias: ['/package/:package(.*)*'],
11+
/**
12+
* Supported patterns:
13+
* /nuxt → packageName: "nuxt", requestedVersion: null
14+
* /nuxt/v/4.2.0 → packageName: "nuxt", requestedVersion: "4.2.0"
15+
* /@nuxt/kit → packageName: "@nuxt/kit", requestedVersion: null
16+
* /@nuxt/kit/v/1.0.0 → packageName: "@nuxt/kit", requestedVersion: "1.0.0"
17+
* /axios@1.13.3 → packageName: "axios", requestedVersion: "1.13.3"
18+
* /@nuxt/kit@1.0.0 → packageName: "@nuxt/kit", requestedVersion: "1.0.0"
19+
*/
20+
path: '/:org(@[^/]+/)?:name([^@/]+):version()?',
21+
alias: [
22+
'/:org(@[^/]+/)?:name([^@/]+)/v/:version()?',
23+
'/package/:org(@[^/]+/)?:name([^@/]+):version()?',
24+
'/package/:org(@[^/]+/)?:name([^@/]+)/v/:version()?',
25+
],
1226
})
1327
1428
const route = useRoute('package')
1529
1630
const router = useRouter()
1731
18-
// Parse package name and optional version from URL
19-
// Patterns:
20-
// /nuxt → packageName: "nuxt", requestedVersion: null
21-
// /nuxt/v/4.2.0 → packageName: "nuxt", requestedVersion: "4.2.0"
22-
// /@nuxt/kit → packageName: "@nuxt/kit", requestedVersion: null
23-
// /@nuxt/kit/v/1.0.0 → packageName: "@nuxt/kit", requestedVersion: "1.0.0"
24-
// /axios@1.13.3 → packageName: "axios", requestedVersion: "1.13.3"
25-
// /@nuxt/kit@1.0.0 → packageName: "@nuxt/kit", requestedVersion: "1.0.0"
26-
const parsedRoute = computed(() => {
27-
const segments = route.params.package || []
28-
29-
// Find the /v/ separator for version
30-
const vIndex = segments.indexOf('v')
31-
if (vIndex !== -1 && vIndex < segments.length - 1) {
32-
return {
33-
packageName: segments.slice(0, vIndex).join('/'),
34-
requestedVersion: segments.slice(vIndex + 1).join('/'),
35-
}
36-
}
37-
38-
// Parse @ versioned package
39-
const fullPath = segments.join('/')
40-
const versionMatch = fullPath.match(/^(@[^/]+\/[^/]+|[^/]+)@([^/]+)$/)
41-
if (versionMatch) {
42-
const [, packageName, requestedVersion] = versionMatch as [string, string, string]
43-
return {
44-
packageName,
45-
requestedVersion,
46-
}
47-
}
48-
49-
return {
50-
packageName: fullPath,
51-
requestedVersion: null as string | null,
52-
}
53-
})
54-
55-
const packageName = computed(() => parsedRoute.value.packageName)
56-
const requestedVersion = computed(() => parsedRoute.value.requestedVersion)
32+
const orgName = computed(() => route.params.org)
33+
const requestedVersion = computed(() => route.params.version || null)
34+
const packageName = computed(() =>
35+
orgName.value ? `${orgName.value}/${route.params.name}` : route.params.name,
36+
)
5737
5838
if (import.meta.server) {
5939
assertValidPackageName(packageName.value)
6040
}
6141
62-
// Extract org name from scoped package (e.g., "@nuxt/kit" -> "nuxt")
63-
const orgName = computed(() => {
64-
const name = packageName.value
65-
if (!name.startsWith('@')) return null
66-
const match = name.match(/^@([^/]+)\//)
67-
return match ? match[1] : null
68-
})
69-
7042
const { data: pkg, status, error, resolvedVersion } = usePackage(packageName, requestedVersion)
7143
7244
const { data: downloads } = usePackageDownloads(packageName, 'last-week')

app/pages/code/[...path].vue

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,10 @@ const orgName = computed(() => {
220220
221221
// Build route object for package link (with optional version)
222222
function packageRoute(ver?: string | null) {
223-
const segments = packageName.value.split('/')
224-
if (ver) {
225-
segments.push('v', ver)
223+
return {
224+
name: 'package' as const,
225+
params: { ...parsePackageRouteParams(packageName.value), version: ver },
226226
}
227-
return { name: 'package' as const, params: { package: segments } }
228227
}
229228
230229
// Format file size

app/pages/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ defineOgImageComponent('Default')
9696
:key="pkg"
9797
>
9898
<NuxtLink
99-
:to="{ name: 'package', params: { package: [pkg] } }"
99+
:to="{ name: 'package', params: parsePackageRouteParams(pkg) }"
100100
class="link-subtle font-mono text-sm inline-flex items-center gap-2 group"
101101
>
102102
<span

0 commit comments

Comments
 (0)