- <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
27 lines
955 B
TypeScript
27 lines
955 B
TypeScript
// Links to the site's own pages from absolute CMS URLs: a URL on the site
|
|
// URL's origin (or on the request origin) becomes its path, so it renders
|
|
// as a NuxtLink; another http(s) URL stays as it is, and anything else
|
|
// (javascript:, data: …) becomes '' so it is never rendered as a link.
|
|
// Pure; names start with `seo` because app/utils is auto-imported.
|
|
|
|
export function seoSitePath(url: string, ...origins: Array<string | undefined | null>): string {
|
|
if (typeof url !== 'string' || url === '') return ''
|
|
if (url.startsWith('/') && !url.startsWith('//')) return url
|
|
let parsed: URL
|
|
try {
|
|
parsed = new URL(url)
|
|
} catch {
|
|
return ''
|
|
}
|
|
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') return ''
|
|
for (const o of origins) {
|
|
if (!o) continue
|
|
try {
|
|
if (new URL(o).origin === parsed.origin) return `${parsed.pathname}${parsed.search}` || '/'
|
|
} catch {
|
|
// not a URL
|
|
}
|
|
}
|
|
return url
|
|
}
|