diff --git a/app/components/Package/Header.vue b/app/components/Package/Header.vue index 571dff4264..8af227e8a9 100644 --- a/app/components/Package/Header.vue +++ b/app/components/Package/Header.vue @@ -164,15 +164,7 @@ const diffLink = computed((): RouteLocationRaw | null => { const timelineLink = computed((): RouteLocationRaw | null => { if (props.pkg == null || props.resolvedVersion == null) return null - const split = props.pkg.name.split('/') - return { - name: 'timeline', - params: { - org: split.length === 2 ? split[0] : undefined, - packageName: split.length === 2 ? split[1]! : split[0]!, - version: props.resolvedVersion, - }, - } + return packageTimelineRoute(props.pkg.name, props.resolvedVersion) }) useShortcuts({ diff --git a/app/composables/useCommandPalettePackageCommands.ts b/app/composables/useCommandPalettePackageCommands.ts index 5533acd5c4..cf09fa5997 100644 --- a/app/composables/useCommandPalettePackageCommands.ts +++ b/app/composables/useCommandPalettePackageCommands.ts @@ -88,6 +88,20 @@ export function useCommandPalettePackageCommands( activeLabel: activeLabel(route.name === 'code', t('command_palette.here')), to: codeLink, }, + { + id: 'package-timeline', + group: 'package', + label: t('package.links.timeline'), + keywords: [ + resolvedContext.packageName, + t('shortcuts.open_timeline'), + t('package.links.timeline'), + ], + iconClass: 'i-lucide:history', + active: route.name === 'timeline', + activeLabel: activeLabel(route.name === 'timeline', t('command_palette.here')), + to: packageTimelineRoute(resolvedContext.packageName, resolvedContext.resolvedVersion), + }, { id: 'package-compare', group: 'package', diff --git a/app/pages/package-timeline/[[org]]/[packageName].vue b/app/pages/package-timeline/[[org]]/[packageName].vue index bb9f577eb0..d368494258 100644 --- a/app/pages/package-timeline/[[org]]/[packageName].vue +++ b/app/pages/package-timeline/[[org]]/[packageName].vue @@ -22,6 +22,8 @@ const packageName = computed(() => const version = computed(() => route.params.version) const { data: pkg } = usePackage(packageName, version) +const { versions: commandPaletteVersions, ensureLoaded: ensureCommandPaletteVersionsLoaded } = + useCommandPalettePackageVersions(packageName) const latestVersion = computed(() => { if (!pkg.value) return null @@ -30,11 +32,32 @@ const latestVersion = computed(() => { return pkg.value.versions[latestTag] ?? null }) +const commandPalettePackageContext = computed(() => { + const packageData = pkg.value + if (!packageData) return null + + return { + packageName: packageData.name, + resolvedVersion: version.value ?? packageData['dist-tags']?.latest ?? null, + latestVersion: packageData['dist-tags']?.latest ?? null, + versions: commandPaletteVersions.value ?? Object.keys(packageData.versions ?? {}), + } +}) + +useCommandPalettePackageContext(commandPalettePackageContext, { + onOpen: ensureCommandPaletteVersionsLoaded, +}) +useCommandPalettePackageCommands(commandPalettePackageContext) + const versionUrlPattern = computed(() => { const { org, packageName: name } = route.params return `/package-timeline/${org ? `${org}/` : ''}${name}/v/{version}` }) +useCommandPaletteVersionCommands(commandPalettePackageContext, nextVersion => + packageTimelineRoute(packageName.value, nextVersion), +) + function packageRoute(ver: string): RouteLocationRaw { return { name: 'package-version', diff --git a/app/utils/router.ts b/app/utils/router.ts index ac3c9a46a6..7fcc8ad898 100644 --- a/app/utils/router.ts +++ b/app/utils/router.ts @@ -52,3 +52,16 @@ export function diffRoute( }, } } + +export function packageTimelineRoute(packageName: string, version: string): RouteLocationRaw { + const { org, name } = splitPackageName(packageName) + + return { + name: 'timeline', + params: { + org: org || undefined, + packageName: name, + version: version.replace(/\s+/g, ''), + }, + } +} diff --git a/test/nuxt/composables/use-command-palette-commands.spec.ts b/test/nuxt/composables/use-command-palette-commands.spec.ts index 650e51de18..ae56784db3 100644 --- a/test/nuxt/composables/use-command-palette-commands.spec.ts +++ b/test/nuxt/composables/use-command-palette-commands.spec.ts @@ -230,6 +230,14 @@ describe('useCommandPaletteCommands', () => { expect(flatCommands.value.find(command => command.id === 'package-diff')).toBeTruthy() expect(flatCommands.value.find(command => command.id === 'package-download')).toBeTruthy() expect(flatCommands.value.find(command => command.id === 'package-main')?.to).toBeTruthy() + expect(flatCommands.value.find(command => command.id === 'package-timeline')?.to).toEqual({ + name: 'timeline', + params: { + org: undefined, + packageName: 'vue', + version: '3.4.0', + }, + }) expect(groupedCommands.value.at(-1)?.id).toBe('versions') expect(groupedCommands.value.at(-1)?.items[0]?.id).toBe('version:3.4.0') expect(groupedCommands.value.at(-1)?.items[0]?.active).toBe(true) @@ -511,6 +519,14 @@ describe('useCommandPaletteCommands', () => { path: ['@scope', 'pkg', 'v', '1.0.0'], }, }) + expect(flatCommands.value.find(command => command.id === 'package-timeline')?.to).toEqual({ + name: 'timeline', + params: { + org: '@scope', + packageName: 'pkg', + version: '1.0.0', + }, + }) wrapper.unmount() })