From 2de6a60104743d6d57584fc44ac68fcbd0af56b5 Mon Sep 17 00:00:00 2001 From: Philippe Serhal Date: Sun, 26 Apr 2026 18:53:27 -0400 Subject: [PATCH 1/2] refactor: accept versioned route builder in cmd palette The placeholder shape made callers that already had named-route helpers resolve routes to strings and then patch encoded placeholders back into place. That was brittle, especially for routes where Vue Router encodes params differently from the URL shape users see. We have a documented guideline that internal navigation should use route object syntax with named routes instead of strings. This commit allows callers to respect that guideline. --- .../useCommandPaletteVersionCommands.ts | 15 ++++++++------ .../[packageName]/v/[versionRange].vue | 20 +++++++++---------- .../v/[version]/[...filePath].vue | 12 ++++++++++- app/pages/package-docs/[...path].vue | 15 +++++++++++++- app/pages/package/[[org]]/[name].vue | 4 +++- .../use-command-palette-commands.spec.ts | 12 +++++------ 6 files changed, 52 insertions(+), 26 deletions(-) diff --git a/app/composables/useCommandPaletteVersionCommands.ts b/app/composables/useCommandPaletteVersionCommands.ts index ecc676e50f..f02b563795 100644 --- a/app/composables/useCommandPaletteVersionCommands.ts +++ b/app/composables/useCommandPaletteVersionCommands.ts @@ -1,5 +1,6 @@ // @unocss-include -import type { MaybeRefOrGetter } from 'vue' +import type { MaybeRef, MaybeRefOrGetter } from 'vue' +import type { RouteLocationRaw } from 'vue-router' import type { CommandPaletteCommand, CommandPaletteContextCommandInput, @@ -7,6 +8,8 @@ import type { } from '~/types/command-palette' import { compare, satisfies, validRange } from 'semver' +type CommandPaletteVersionRoute = (version: string) => RouteLocationRaw + function getSortedVersions(context: CommandPalettePackageContext) { return [...context.versions].sort((a, b) => { if (a === context.resolvedVersion) return -1 @@ -19,7 +22,7 @@ function createVersionCommands( context: CommandPalettePackageContext, t: ReturnType['t'], versions = getSortedVersions(context), - urlPattern?: string | null, + routeForVersion?: CommandPaletteVersionRoute | null, ): CommandPaletteCommand[] { return versions.map(version => ({ id: `version:${version}`, @@ -28,13 +31,13 @@ function createVersionCommands( keywords: [context.packageName, version, t('command_palette.groups.versions')], iconClass: 'i-lucide:tag', active: version === context.resolvedVersion, - to: urlPattern?.replace('{version}', version) ?? packageRoute(context.packageName, version), + to: routeForVersion?.(version) ?? packageRoute(context.packageName, version), })) } export function useCommandPaletteVersionCommands( context: MaybeRefOrGetter, - urlPattern?: MaybeRefOrGetter, + routeForVersion?: MaybeRef, ) { const { t } = useI18n() @@ -43,7 +46,7 @@ export function useCommandPaletteVersionCommands( const resolvedContext = toValue(context) if (!resolvedContext?.resolvedVersion) return [] - return createVersionCommands(resolvedContext, t, undefined, toValue(urlPattern)) + return createVersionCommands(resolvedContext, t, undefined, unref(routeForVersion)) }), ) @@ -58,6 +61,6 @@ export function useCommandPaletteVersionCommands( satisfies(version, semverRange, { includePrerelease: true }), ) - return createVersionCommands(resolvedContext, t, matchingVersions, toValue(urlPattern)) + return createVersionCommands(resolvedContext, t, matchingVersions, unref(routeForVersion)) }) } diff --git a/app/pages/diff/[[org]]/[packageName]/v/[versionRange].vue b/app/pages/diff/[[org]]/[packageName]/v/[versionRange].vue index 1bc6ac2c94..3da147500d 100644 --- a/app/pages/diff/[[org]]/[packageName]/v/[versionRange].vue +++ b/app/pages/diff/[[org]]/[packageName]/v/[versionRange].vue @@ -116,19 +116,19 @@ const latestVersionDetailed = computed(() => { return pkg.value.versions[latestTag] ?? null }) -const normalizeRoutePath = (routeLocation: RouteLocationRaw) => { - const resolvedHref = router.resolve(routeLocation).href - return resolvedHref.replace(/%7B/g, '{').replace(/%7D/g, '}') +function diffVersionUrlPattern(from: string, to: string) { + const { org, packageName: name } = route.params + return `/diff/${org ? `${org}/` : ''}${name}/v/${from}...${to}` } -const fromVersionUrlPattern = computed(() => { - return normalizeRoutePath(diffRoute(packageName.value, '{version}', toVersion.value)) -}) -const toVersionUrlPattern = computed(() => { - return normalizeRoutePath(diffRoute(packageName.value, fromVersion.value, '{version}')) -}) +const fromVersionUrlPattern = computed(() => diffVersionUrlPattern('{version}', toVersion.value)) +const toVersionUrlPattern = computed(() => diffVersionUrlPattern(fromVersion.value, '{version}')) + +function fromVersionRoute(version: string): RouteLocationRaw { + return diffRoute(packageName.value, version, toVersion.value) +} -useCommandPaletteVersionCommands(commandPalettePackageContext, fromVersionUrlPattern) +useCommandPaletteVersionCommands(commandPalettePackageContext, fromVersionRoute) useSeoMeta({ title: () => { diff --git a/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue b/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue index 8c2e43988d..8bdfa23c43 100644 --- a/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue +++ b/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue @@ -1,4 +1,5 @@