From ba5117c9f7a4df91bd6b2f44cc6db97885f439b2 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 18 Mar 2026 07:07:05 +0000 Subject: [PATCH 1/4] fix(ng-website): honor base urls in nav links Co-authored-by: Michael Villalba Sotelo --- .../src/app/pages/home/hero/hero.html | 11 +-- .../src/app/pages/home/hero/hero.ts | 11 ++- .../src/app/shared/app-href.spec.ts | 33 +++++++++ apps/ng-website/src/app/shared/app-href.ts | 70 +++++++++++++++++++ .../src/app/shared/layout/navbar/navbar.html | 7 +- .../src/app/shared/layout/navbar/navbar.ts | 39 +++-------- 6 files changed, 134 insertions(+), 37 deletions(-) create mode 100644 apps/ng-website/src/app/shared/app-href.spec.ts create mode 100644 apps/ng-website/src/app/shared/app-href.ts diff --git a/apps/ng-website/src/app/pages/home/hero/hero.html b/apps/ng-website/src/app/pages/home/hero/hero.html index 90baacc..369077d 100644 --- a/apps/ng-website/src/app/pages/home/hero/hero.html +++ b/apps/ng-website/src/app/pages/home/hero/hero.html @@ -14,11 +14,12 @@ -

- Transforming - +

+ Transforming Ideas into Reality. @@ -47,7 +48,7 @@

Resume diff --git a/apps/ng-website/src/app/pages/home/hero/hero.ts b/apps/ng-website/src/app/pages/home/hero/hero.ts index 57bc6af..bfc9072 100644 --- a/apps/ng-website/src/app/pages/home/hero/hero.ts +++ b/apps/ng-website/src/app/pages/home/hero/hero.ts @@ -1,4 +1,7 @@ -import { Component } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { computed, Component, inject } from '@angular/core'; + +import { getAppHref } from '../../../shared/app-href'; @Component({ selector: 'app-hero', @@ -9,4 +12,8 @@ import { Component } from '@angular/core'; class: /* tw */ 'relative z-10 flex min-h-screen flex-col items-center justify-center px-6 text-center', }, }) -export class Hero {} +export class Hero { + private readonly document = inject(DOCUMENT); + + readonly resumeHref = computed(() => getAppHref(this.document.baseURI, '/resume')); +} diff --git a/apps/ng-website/src/app/shared/app-href.spec.ts b/apps/ng-website/src/app/shared/app-href.spec.ts new file mode 100644 index 0000000..fadc7b8 --- /dev/null +++ b/apps/ng-website/src/app/shared/app-href.spec.ts @@ -0,0 +1,33 @@ +import { getAppHref, getDeploymentBasePath, getLocaleHref } from './app-href'; + +describe('app href helpers', () => { + it('should build root-based app hrefs', () => { + expect(getDeploymentBasePath('https://example.com/')).toBe('/'); + expect(getAppHref('https://example.com/', '/')).toBe('/'); + expect(getAppHref('https://example.com/', '/resume')).toBe('/resume'); + }); + + it('should build GitHub Pages app hrefs from the deployment base path', () => { + expect(getDeploymentBasePath('https://example.com/visomi.dev/')).toBe('/visomi.dev/'); + expect(getAppHref('https://example.com/visomi.dev/', '/')).toBe('/visomi.dev/'); + expect(getAppHref('https://example.com/visomi.dev/', '/projects')).toBe('/visomi.dev/projects'); + }); + + it('should build locale hrefs within a GitHub Pages deployment', () => { + const documentBaseUri = 'https://example.com/visomi.dev/'; + + expect(getLocaleHref(documentBaseUri, '/', 'en')).toBe('/visomi.dev/'); + expect(getLocaleHref(documentBaseUri, '/resume?download=1#top', 'en')).toBe('/visomi.dev/resume?download=1#top'); + expect(getLocaleHref(documentBaseUri, '/resume?download=1#top', 'es')).toBe( + '/visomi.dev/es/resume?download=1#top', + ); + }); + + it('should switch locale paths from a localized deployment base path', () => { + const localizedBaseUri = 'https://example.com/visomi.dev/es/'; + + expect(getDeploymentBasePath(localizedBaseUri)).toBe('/visomi.dev/'); + expect(getLocaleHref(localizedBaseUri, '/', 'en')).toBe('/visomi.dev/'); + expect(getLocaleHref(localizedBaseUri, '/projects', 'es')).toBe('/visomi.dev/es/projects'); + }); +}); diff --git a/apps/ng-website/src/app/shared/app-href.ts b/apps/ng-website/src/app/shared/app-href.ts new file mode 100644 index 0000000..7889d46 --- /dev/null +++ b/apps/ng-website/src/app/shared/app-href.ts @@ -0,0 +1,70 @@ +const FALLBACK_ORIGIN = 'http://localhost'; +const SPANISH_LOCALE = 'es'; + +function ensureLeadingSlash(pathname: string) { + return pathname ? (pathname.startsWith('/') ? pathname : `/${pathname}`) : '/'; +} + +function ensureTrailingSlash(pathname: string) { + return pathname.endsWith('/') ? pathname : `${pathname}/`; +} + +function trimTrailingSlash(pathname: string) { + if (pathname === '/') { + return pathname; + } + + return pathname.endsWith('/') ? pathname.slice(0, -1) : pathname; +} + +function stripLocaleSuffix(pathname: string) { + const normalizedPathname = trimTrailingSlash(ensureLeadingSlash(pathname)); + + if (normalizedPathname === `/${SPANISH_LOCALE}`) { + return '/'; + } + + const localeSuffix = `/${SPANISH_LOCALE}`; + + return normalizedPathname.endsWith(localeSuffix) + ? (normalizedPathname.slice(0, -localeSuffix.length) || '/') + : normalizedPathname; +} + +function stripLocalePrefix(pathname: string) { + const normalizedPathname = ensureLeadingSlash(pathname); + const localePrefix = `/${SPANISH_LOCALE}`; + + if (normalizedPathname === localePrefix || normalizedPathname === `${localePrefix}/`) { + return '/'; + } + + return normalizedPathname.startsWith(`${localePrefix}/`) + ? normalizedPathname.slice(localePrefix.length) + : normalizedPathname; +} + +export function getDeploymentBasePath(documentBaseUri: string) { + const pathname = new URL(documentBaseUri, FALLBACK_ORIGIN).pathname; + + return ensureTrailingSlash(stripLocaleSuffix(pathname)); +} + +export function getAppHref(documentBaseUri: string, appPath: string) { + const basePath = getDeploymentBasePath(documentBaseUri); + const normalizedAppPath = ensureLeadingSlash(appPath); + + if (normalizedAppPath === '/') { + return basePath; + } + + return `${basePath}${normalizedAppPath.slice(1)}`; +} + +export function getLocaleHref(documentBaseUri: string, currentPath: string, target: 'en' | 'es') { + const currentUrl = new URL(currentPath || '/', FALLBACK_ORIGIN); + const pathname = stripLocalePrefix(currentUrl.pathname); + const localizedPath = target === 'es' ? (pathname === '/' ? '/es/' : `/es${pathname}`) : pathname; + + return `${getAppHref(documentBaseUri, localizedPath)}${currentUrl.search}${currentUrl.hash}`; +} diff --git a/apps/ng-website/src/app/shared/layout/navbar/navbar.html b/apps/ng-website/src/app/shared/layout/navbar/navbar.html index 7ab4d13..543bbc5 100644 --- a/apps/ng-website/src/app/shared/layout/navbar/navbar.html +++ b/apps/ng-website/src/app/shared/layout/navbar/navbar.html @@ -1,12 +1,13 @@