Skip to content

Commit

Permalink
fix: better isActive check that includes query parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
TylorS committed May 20, 2024
1 parent a96ca73 commit 5f64445
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 11 deletions.
2 changes: 1 addition & 1 deletion examples/realworld/src/ui/components/Pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ function renderPagination<R>(
)

return html`<li class="page-item ${activeClassName}">
${Link({ to: RefSubject.map(page, (p) => `?page=${p}`), className: "page-link" }, page)}
${Link({ to: RefSubject.map(page, (p) => `?page=${p}`), className: "page-link", relative: true }, page)}
</li>`
}
4 changes: 4 additions & 0 deletions packages/fx/src/internal/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,10 @@ const toDeepEquals = (u: unknown): unknown => {
return Data.tuple(Array.from(u, toDeepEquals))
} else if (u instanceof Map) {
return Data.tuple(Array.from(u, ([k, v]) => Data.tuple([toDeepEquals(k), toDeepEquals(v)])))
} else if (u instanceof URLSearchParams) {
return Data.tuple(Array.from(u.keys()).map((key) => Data.tuple([key, toDeepEquals(u.getAll(key))])))
} else if (Symbol.iterator in u) {
return Data.tuple(Array.from(u as any, toDeepEquals))
} else {
return Data.struct(Record.map(u, toDeepEquals))
}
Expand Down
54 changes: 44 additions & 10 deletions packages/router/src/CurrentRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,51 @@ const isActive_ = (

const fullRoute = currentRoute.concat(route)
const fullParams = { ...currentMatch.value, ...params }
const fullPath: string = fullRoute.interpolate(fullParams as any)
const currentPathWithoutSearch = currentPath.split("?")[0] || "/"
const fullPathWithoutSearch = fullPath.split("?")[0] || "/"

if (fullPathWithoutSearch === currentPathWithoutSearch) {
return true
} else if (route.routeOptions.end) {
return false
} else {
return currentPathWithoutSearch.startsWith(fullPathWithoutSearch)
const href: string = fullRoute.interpolate(fullParams as any)
const [currentPathname, currentQuery] = splitByQuery(currentPath)
const [hrefPathname, hrefQuery] = splitByQuery(href)

return (fullRoute.routeOptions.end ? currentPathname === hrefPathname : currentPathname.startsWith(hrefPathname)) &&
compareQueries(currentQuery, hrefQuery)
}

function compareQueries(currentQuery: string, hrefQuery: string) {
// if hrefQuery is empty, it means that the href is a pathname only
if (!hrefQuery) return true
// if currentQuery is empty, there is no match at this point
if (!currentQuery) return false
// if the queries are equal, there is a match
if (currentQuery === hrefQuery) return true

const currentQueryParams = new URLSearchParams(currentQuery)
const hrefQueryParams = new URLSearchParams(hrefQuery)

for (const key of hrefQueryParams.keys()) {
const a = currentQueryParams.getAll(key).sort()
const b = hrefQueryParams.getAll(key).sort()

if (a.length !== b.length || !b.every((bx, i) => a[i] === bx)) return false
}

return true
}

function splitByQuery(path: string) {
const ptrSyntaxIndex = path.indexOf("\\?")
if (ptrSyntaxIndex > -1) {
const pathname = path.slice(0, ptrSyntaxIndex)
const query = path.slice(ptrSyntaxIndex + 1).trim()
return [pathname, query] as const
}

const queryIndex = path.indexOf("?")
if (queryIndex > -1) {
const pathname = path.slice(0, queryIndex)
const query = path.slice(queryIndex + 1).trim()
return [pathname, query] as const
}

return [path, ""] as const
}

/**
Expand Down

0 comments on commit 5f64445

Please sign in to comment.