@@ -5,16 +5,21 @@ import type {
55 PackageFileContentResponse ,
66} from ' #shared/types'
77
8- const route = useRoute (' package-code-path' )
8+ definePageMeta ({
9+ name: ' code' ,
10+ alias: [' /package/code/:path(.*)*' ],
11+ })
12+
13+ const route = useRoute (' code' )
914const router = useRouter ()
1015
1116// Parse package name, version, and file path from URL
1217// Patterns:
13- // /package/ code/nuxt/v/4.2.0 → packageName: "nuxt", version: "4.2.0", filePath: null (show tree)
14- // /package/ code/nuxt/v/4.2.0/src/index.ts → packageName: "nuxt", version: "4.2.0", filePath: "src/index.ts"
15- // /package/ code/@nuxt/kit/v/1.0.0 → packageName: "@nuxt/kit", version: "1.0.0", filePath: null
18+ // /code/nuxt/v/4.2.0 → packageName: "nuxt", version: "4.2.0", filePath: null (show tree)
19+ // /code/nuxt/v/4.2.0/src/index.ts → packageName: "nuxt", version: "4.2.0", filePath: "src/index.ts"
20+ // /code/@nuxt/kit/v/1.0.0 → packageName: "@nuxt/kit", version: "1.0.0", filePath: null
1621const parsedRoute = computed (() => {
17- const segments = Array . isArray ( route .params .path ) ? route . params . path : [ route . params . path ?? ' ' ]
22+ const segments = route .params .path || [ ]
1823
1924 // Find the /v/ separator for version
2025 const vIndex = segments .indexOf (' v' )
@@ -75,8 +80,8 @@ const availableVersions = computed(() => {
7580// Version switch handler
7681function switchVersion(newVersion : string ) {
7782 const newPath = filePath .value
78- ? ` /package/ code/${packageName .value }/v/${newVersion }/${filePath .value } `
79- : ` /package/ code/${packageName .value }/v/${newVersion } `
83+ ? ` /code/${packageName .value }/v/${newVersion }/${filePath .value } `
84+ : ` /code/${packageName .value }/v/${newVersion } `
8085 router .push (newPath )
8186}
8287
@@ -207,7 +212,7 @@ const breadcrumbs = computed(() => {
207212
208213// Navigation helper - build URL for a path
209214function getCodeUrl(path ? : string ): string {
210- const base = ` /package/ code/${packageName .value }/v/${version .value } `
215+ const base = ` /code/${packageName .value }/v/${version .value } `
211216 return path ? ` ${base }/${path } ` : base
212217}
213218
@@ -219,6 +224,15 @@ const orgName = computed(() => {
219224 return match ? match [1 ] : null
220225})
221226
227+ // Build route object for package link (with optional version)
228+ function packageRoute(ver ? : string | null ) {
229+ const segments = packageName .value .split (' /' )
230+ if (ver ) {
231+ segments .push (' v' , ver )
232+ }
233+ return { name: ' package' as const , params: { package: segments } }
234+ }
235+
222236// Format file size
223237function formatBytes(bytes : number ): string {
224238 if (bytes < 1024 ) return ` ${bytes } B `
@@ -257,6 +271,19 @@ async function copyPermalink() {
257271 await navigator .clipboard .writeText (url .toString ())
258272}
259273
274+ // Canonical URL for this code page
275+ const canonicalUrl = computed (() => {
276+ let url = ` https://npmx.dev/code/${packageName .value }/v/${version .value } `
277+ if (filePath .value ) {
278+ url += ` /${filePath .value } `
279+ }
280+ return url
281+ })
282+
283+ useHead ({
284+ link: [{ rel: ' canonical' , href: canonicalUrl }],
285+ })
286+
260287useSeoMeta ({
261288 title : () => {
262289 if (filePath .value ) {
@@ -276,7 +303,7 @@ useSeoMeta({
276303 <!-- Package info and navigation -->
277304 <div class =" flex items-center gap-2 mb-3 flex-wrap" >
278305 <NuxtLink
279- :to =" `/package/${packageName}${ version ? `/v/${version}` : ''}` "
306+ :to =" packageRoute( version) "
280307 class =" font-mono text-lg font-medium hover:text-fg transition-colors"
281308 >
282309 <span v-if =" orgName" class =" text-fg-muted" >@{{ orgName }}/</span
@@ -337,7 +364,7 @@ useSeoMeta({
337364 <!-- Error: no version -->
338365 <div v-if =" !version" class =" container py-20 text-center" >
339366 <p class =" text-fg-muted mb-4" >Version is required to browse code</p >
340- <NuxtLink :to =" `/package/${packageName}` " class =" btn" > Go to package </NuxtLink >
367+ <NuxtLink :to =" packageRoute() " class =" btn" > Go to package </NuxtLink >
341368 </div >
342369
343370 <!-- Loading state -->
@@ -349,9 +376,7 @@ useSeoMeta({
349376 <!-- Error state -->
350377 <div v-else-if =" treeStatus === 'error'" class =" container py-20 text-center" role =" alert" >
351378 <p class =" text-fg-muted mb-4" >Failed to load files for this package version</p >
352- <NuxtLink :to =" `/package/${packageName}${version ? `/v/${version}` : ''}`" class =" btn" >
353- Back to package
354- </NuxtLink >
379+ <NuxtLink :to =" packageRoute(version)" class =" btn" > Back to package </NuxtLink >
355380 </div >
356381
357382 <!-- Main content: file tree + file viewer -->
0 commit comments