Files
vue-seo-layer/app/utils/breadcrumbClaim.ts
Jakub Zych ebb0c8084e feat: breadcrumbs component
- <SeoBreadcrumbs> (UI-SPEC L1): the resolve answer's trail as nav > ol
  with server-rendered links and the last item as aria-current text;
  nothing with fewer than two items, with page meta seo.breadcrumbs false
  or with the option seo.breadcrumbs false; props items, label,
  hideCurrent, locale
- one trail per page: the first rendered instance claims it
  (seoClaimBreadcrumbs, kept per path)
- seoSitePath: same-origin CMS URLs become paths, non-http(s) URLs are
  never links; useSeoLabels takes an optional locale
- L1 default styles with CSS-generated separators
2026-11-04 11:59:17 +01:00

28 lines
1.2 KiB
TypeScript

// One visible breadcrumb trail per page (UI-SPEC L1): an app may place
// <SeoBreadcrumbs> in its layout while a layer's page renders one too; the
// first instance that renders in a request claims the page and later ones
// render nothing. The claim is kept per path, so a client navigation hands
// it out again (the layout instance, set up first, claims first). Pure, so
// `node --test` drives it; names start with `seo` (app/utils is
// auto-imported).
export interface SeoBreadcrumbClaim {
path: string
id: string
}
/**
* Whether instance `id` owns the trail of `path`, and the claim to keep:
* no claim or one for another path is taken over; the claim of this path
* belongs to the instance that made it.
*/
export function seoClaimBreadcrumbs(state: SeoBreadcrumbClaim | null | undefined, path: string, id: string): { state: SeoBreadcrumbClaim; owns: boolean } {
if (!state || state.path !== path) return { state: { path, id }, owns: true }
return { state, owns: state.id === id }
}
/** Releases the claim of `id` (an instance that stops rendering its trail). */
export function seoReleaseBreadcrumbs(state: SeoBreadcrumbClaim | null | undefined, id: string): SeoBreadcrumbClaim | null {
return state && state.id === id ? null : (state ?? null)
}