Skip to content

Conversation

@essenmitsosse
Copy link
Contributor

@essenmitsosse essenmitsosse commented Feb 9, 2026

This is the first step to get rid of the catch all segments in routing.

If this looks good and we want to continue like this, I would like to change all routes to be properly described. Once they are all converted, a lot of the manual path splitting and build code can disappear and we can just pass around the route objects which should remove a lot of boiler plate code. It also will improve typing.

This also "fixes" the escaping of the slash in package names with an org.

@vercel
Copy link

vercel bot commented Feb 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Feb 9, 2026 10:50pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Feb 9, 2026 10:50pm
npmx-lunaria Ignored Ignored Feb 9, 2026 10:50pm

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR replaces the array-based basePath: string[] prop with a named-route prop baseRoute: Pick<RouteNamedMap['code'], 'params'> across DirectoryListing, FileTree, MobileTreeDrawer and related components, and updates InstallScripts and package pages to build RouteLocationRaw objects using params (org, packageName, version, filePath). The package-code page route is adjusted to accept optional org scope and a catch-all filePath; route builders and URL helpers are refactored to use route.params directly.

Possibly related PRs

Suggested reviewers

  • danielroe
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The PR description clearly relates to the changeset, describing a refactoring to replace catch-all routing segments with properly described route segments and addressing scoped package name escaping.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/pages/package/[[org]]/[name].vue (1)

519-533: Avoid non‑null assertions when splitting package names.

The split array indices are asserted with !. Prefer explicit guards to keep index access type‑safe and avoid unexpected runtime issues when the name is malformed.
As per coding guidelines, "Ensure you write strictly type-safe code, for example by ensuring you always check when accessing an array value by index".

♻️ Suggested refactor
-const linkCode = computed((): Parameters<typeof navigateTo>[0] | null => {
-  if (pkg.value == null || resolvedVersion.value == null) {
-    return null
-  }
-  const split = pkg.value.name.split('/')
-  return {
-    name: 'code',
-    params: {
-      org: split.length === 2 ? split[0]?.replace(/^@/, '') : undefined,
-      packageName: split.length === 2 ? split[1]! : split[0]!,
-      version: resolvedVersion.value,
-      filePath: '',
-    },
-  }
-})
+const linkCode = computed((): Parameters<typeof navigateTo>[0] | null => {
+  if (pkg.value == null || resolvedVersion.value == null) return null
+
+  const [first, second] = pkg.value.name.split('/')
+  const isScoped = pkg.value.name.startsWith('@') && !!second
+  const packageName = isScoped ? second : first
+  if (!packageName) return null
+
+  return {
+    name: 'code',
+    params: {
+      org: isScoped ? first.replace(/^@/, '') : undefined,
+      packageName,
+      version: resolvedVersion.value,
+      filePath: '',
+    },
+  }
+})

@danielroe
Copy link
Member

this is absolutely something we should be doing - would you check the failing CI?

@codecov
Copy link

codecov bot commented Feb 9, 2026

Codecov Report

❌ Patch coverage is 47.36842% with 10 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/pages/package/[[org]]/[name].vue 0.00% 8 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

@essenmitsosse
Copy link
Contributor Author

Ok, so unfortunately there is no elegant way to enforce the @ for the org while having the segment optional, but we can just make it entirely optional, without enforcing the @ which is still an improvement over before.

@danielroe should be fine now.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Comment on lines +15 to +27
function getCodeLink(filePath: string): RouteLocationRaw {
const split = props.packageName.split('/')

console.log({ split })
return {
name: 'code',
params: {
org: split.length === 2 ? split[0] : null,
packageName: split.length === 2 ? split[1]! : split[0]!,
version: props.version,
filePath: '',
},
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use filePath and avoid null for org when building code links.

getCodeLink currently ignores the filePath argument (so links always go to the root) and sets org to null, which can produce /package-code/null/... for unscoped packages. Also, the debug console.log should be removed.

💡 Suggested fix
 function getCodeLink(filePath: string): RouteLocationRaw {
-  const split = props.packageName.split('/')
-
-  console.log({ split })
+  const scopedName = props.packageName.startsWith('@')
+  const [org, name] = scopedName
+    ? props.packageName.slice(1).split('/')
+    : [undefined, props.packageName]
   return {
     name: 'code',
     params: {
-      org: split.length === 2 ? split[0] : null,
-      packageName: split.length === 2 ? split[1]! : split[0]!,
+      org,
+      packageName: name,
       version: props.version,
-      filePath: '',
+      filePath,
     },
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function getCodeLink(filePath: string): RouteLocationRaw {
const split = props.packageName.split('/')
console.log({ split })
return {
name: 'code',
params: {
org: split.length === 2 ? split[0] : null,
packageName: split.length === 2 ? split[1]! : split[0]!,
version: props.version,
filePath: '',
},
}
function getCodeLink(filePath: string): RouteLocationRaw {
const scopedName = props.packageName.startsWith('@')
const [org, name] = scopedName
? props.packageName.slice(1).split('/')
: [undefined, props.packageName]
return {
name: 'code',
params: {
org,
packageName: name,
version: props.version,
filePath,
},
}
}

Comment on lines +520 to +533
const codeLink = computed((): RouteLocationRaw | null => {
if (pkg.value == null || resolvedVersion.value == null) {
return null
}
const split = pkg.value.name.split('/')
return {
name: 'code',
params: {
org: split.length === 2 ? split[0] : undefined,
packageName: split.length === 2 ? split[1]! : split[0]!,
version: resolvedVersion.value,
filePath: '',
},
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Strip the leading “@” when building org for code routes.

For scoped packages, pkg.value.name is @scope/pkg, so split[0] includes @. The code page reconstructs as @${org}/${packageName}, which becomes @@scope/pkg and breaks code navigation for scoped packages. Use orgName or strip the prefix before setting params.

💡 Suggested fix
-  const split = pkg.value.name.split('/')
-  return {
-    name: 'code',
-    params: {
-      org: split.length === 2 ? split[0] : undefined,
-      packageName: split.length === 2 ? split[1]! : split[0]!,
-      version: resolvedVersion.value,
-      filePath: '',
-    },
-  }
+  const scopedName = pkg.value.name.startsWith('@')
+  const [org, name] = scopedName
+    ? pkg.value.name.slice(1).split('/')
+    : [undefined, pkg.value.name]
+  return {
+    name: 'code',
+    params: {
+      org,
+      packageName: name,
+      version: resolvedVersion.value,
+      filePath: undefined,
+    },
+  }

@danielroe
Copy link
Member

danielroe commented Feb 9, 2026

seems like a couple of good comments from @coderabbitai 🙏

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Tip

For best results, initiate chat on the files or code changes.

@danielroe Thank you! Happy to help with the review. Let me know if you need anything else as this PR progresses. 🚀

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Tip

For best results, initiate chat on the files or code changes.

@danielroe Thank you for the kind words! 🙏 I'm happy to help ensure the refactoring is solid. If you have any questions about my comments or need clarification on any of the suggestions, feel free to ask!

(ノ◕ヮ◕)ノ*:・゚✧ 🐰

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Comment on lines +203 to +207
function getCurrentCodeUrl(path?: string): string {
return getCodeUrl({
...route.params,
filePath: path,
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Preserve the current file path when building URLs.
getCurrentCodeUrl() overwrites filePath with undefined when called without a path, so Line 251’s canonical URL (and any no-arg use) points to the package root even when a file is open. Only override filePath when a value is provided.

💡 Suggested fix
 function getCurrentCodeUrl(path?: string): string {
   return getCodeUrl({
     ...route.params,
-    filePath: path,
+    ...(path !== undefined ? { filePath: path } : {}),
   })
 }

Also applies to: 251-251

@danielroe
Copy link
Member

there may be some patterns here: #158 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants